1
|
|
|
<?php |
2
|
|
|
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); |
3
|
|
|
/********************************************************************************* |
4
|
|
|
* SugarCRM Community Edition is a customer relationship management program developed by |
5
|
|
|
* SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc. |
6
|
|
|
|
7
|
|
|
* SuiteCRM is an extension to SugarCRM Community Edition developed by Salesagility Ltd. |
8
|
|
|
* Copyright (C) 2011 - 2014 Salesagility Ltd. |
9
|
|
|
* |
10
|
|
|
* This program is free software; you can redistribute it and/or modify it under |
11
|
|
|
* the terms of the GNU Affero General Public License version 3 as published by the |
12
|
|
|
* Free Software Foundation with the addition of the following permission added |
13
|
|
|
* to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK |
14
|
|
|
* IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY |
15
|
|
|
* OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. |
16
|
|
|
* |
17
|
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT |
18
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
19
|
|
|
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more |
20
|
|
|
* details. |
21
|
|
|
* |
22
|
|
|
* You should have received a copy of the GNU Affero General Public License along with |
23
|
|
|
* this program; if not, see http://www.gnu.org/licenses or write to the Free |
24
|
|
|
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
25
|
|
|
* 02110-1301 USA. |
26
|
|
|
* |
27
|
|
|
* You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road, |
28
|
|
|
* SW2-130, Cupertino, CA 95014, USA. or at email address [email protected]. |
29
|
|
|
* |
30
|
|
|
* The interactive user interfaces in modified source and object code versions |
31
|
|
|
* of this program must display Appropriate Legal Notices, as required under |
32
|
|
|
* Section 5 of the GNU Affero General Public License version 3. |
33
|
|
|
* |
34
|
|
|
* In accordance with Section 7(b) of the GNU Affero General Public License version 3, |
35
|
|
|
* these Appropriate Legal Notices must retain the display of the "Powered by |
36
|
|
|
* SugarCRM" logo and "Supercharged by SuiteCRM" logo. If the display of the logos is not |
37
|
|
|
* reasonably feasible for technical reasons, the Appropriate Legal Notices must |
38
|
|
|
* display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM". |
39
|
|
|
********************************************************************************/ |
40
|
|
|
|
41
|
|
|
/********************************************************************************* |
42
|
|
|
|
43
|
|
|
* Description: |
44
|
|
|
* Portions created by SugarCRM are Copyright (C) SugarCRM, Inc. All Rights |
45
|
|
|
* Reserved. Contributor(s): ______________________________________.. |
46
|
|
|
*********************************************************************************/ |
47
|
|
|
|
48
|
|
|
require_once("include/ytree/Tree.php"); |
49
|
|
|
require_once("include/ytree/ExtNode.php"); |
50
|
|
|
require_once("include/SugarFolders/SugarFolders.php"); |
51
|
|
|
|
52
|
|
|
|
53
|
|
|
|
54
|
|
|
class EmailUI { |
55
|
|
|
var $db; |
56
|
|
|
var $folder; // place holder for SugarFolder object |
57
|
|
|
var $folderStates = array(); // array of folderPath names and their states (1/0) |
58
|
|
|
var $smarty; |
59
|
|
|
var $addressSeparators = array(";", ","); |
60
|
|
|
var $rolloverStyle = "<style>div#rollover {position: relative;float: left;margin: none;text-decoration: none;}div#rollover a:hover {padding: 0;}div#rollover a span {display: none;}div#rollover a:hover span {text-decoration: none;display: block;width: 250px;margin-top: 5px;margin-left: 5px;position: absolute;padding: 10px;color: #333; border: 1px solid #ccc; background-color: #fff; font-size: 12px;z-index: 1000;}</style>\n"; |
61
|
|
|
var $groupCss = "<span class='groupInbox'>"; |
62
|
|
|
var $cacheTimeouts = array( |
63
|
|
|
'messages' => 86400, // 24 hours |
64
|
|
|
'folders' => 300, // 5 mins |
65
|
|
|
'attachments' => 86400, // 24 hours |
66
|
|
|
); |
67
|
|
|
var $userCacheDir = ''; |
68
|
|
|
var $coreDynamicFolderQuery = "SELECT emails.id polymorphic_id, 'Emails' polymorphic_module FROM emails |
69
|
|
|
JOIN emails_text on emails.id = emails_text.email_id |
70
|
|
|
WHERE (type = '::TYPE::' OR status = '::STATUS::') AND assigned_user_id = '::USER_ID::' AND emails.deleted = '0'"; |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* Sole constructor |
74
|
|
|
*/ |
75
|
|
|
function EmailUI() { |
76
|
|
|
global $sugar_config; |
77
|
|
|
global $current_user; |
78
|
|
|
|
79
|
|
|
$folderStateSerial = $current_user->getPreference('folderOpenState', 'Emails'); |
80
|
|
|
|
81
|
|
|
if(!empty($folderStateSerial)) { |
82
|
|
|
$this->folderStates = unserialize($folderStateSerial); |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
$this->smarty = new Sugar_Smarty(); |
86
|
|
|
$this->folder = new SugarFolder(); |
87
|
|
|
$this->userCacheDir = sugar_cached("modules/Emails/{$current_user->id}"); |
88
|
|
|
$this->db = DBManagerFactory::getInstance(); |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
|
92
|
|
|
/////////////////////////////////////////////////////////////////////////// |
93
|
|
|
//// CORE |
94
|
|
|
/** |
95
|
|
|
* Renders the frame for emails |
96
|
|
|
*/ |
97
|
|
|
function displayEmailFrame() { |
98
|
|
|
|
99
|
|
|
require_once("include/OutboundEmail/OutboundEmail.php"); |
100
|
|
|
|
101
|
|
|
global $app_strings, $app_list_strings; |
102
|
|
|
global $mod_strings; |
103
|
|
|
global $sugar_config; |
104
|
|
|
global $current_user; |
105
|
|
|
global $locale; |
106
|
|
|
global $timedate; |
107
|
|
|
global $theme; |
108
|
|
|
global $sugar_version; |
109
|
|
|
global $sugar_flavor; |
110
|
|
|
global $current_language; |
111
|
|
|
global $server_unique_key; |
112
|
|
|
|
113
|
|
|
$this->preflightUserCache(); |
114
|
|
|
$ie = new InboundEmail(); |
115
|
|
|
|
116
|
|
|
// focus listView |
117
|
|
|
$list = array( |
118
|
|
|
'mbox' => 'Home', |
119
|
|
|
'ieId' => '', |
120
|
|
|
'name' => 'Home', |
121
|
|
|
'unreadChecked' => 0, |
122
|
|
|
'out' => array(), |
123
|
|
|
); |
124
|
|
|
|
125
|
|
|
$this->_generateComposeConfigData('email_compose'); |
126
|
|
|
|
127
|
|
|
|
128
|
|
|
//Check quick create module access |
129
|
|
|
$QCAvailableModules = $this->_loadQuickCreateModules(); |
130
|
|
|
|
131
|
|
|
//Get the quickSearch js needed for assigned user id on Search Tab |
132
|
|
|
require_once('include/QuickSearchDefaults.php'); |
133
|
|
|
$qsd = QuickSearchDefaults::getQuickSearchDefaults(); |
134
|
|
|
$qsd->setFormName('advancedSearchForm'); |
135
|
|
|
$quicksearchAssignedUser = "if(typeof sqs_objects == 'undefined'){var sqs_objects = new Array;}"; |
136
|
|
|
$quicksearchAssignedUser .= "sqs_objects['advancedSearchForm_assigned_user_name']=" . json_encode($qsd->getQSUser()) . ";"; |
137
|
|
|
$qsd->setFormName('Distribute'); |
138
|
|
|
$quicksearchAssignedUser .= "sqs_objects['Distribute_assigned_user_name']=" . json_encode($qsd->getQSUser()) . ";"; |
139
|
|
|
$this->smarty->assign('quickSearchForAssignedUser', $quicksearchAssignedUser); |
140
|
|
|
|
141
|
|
|
|
142
|
|
|
/////////////////////////////////////////////////////////////////////// |
143
|
|
|
//// BASIC ASSIGNS |
144
|
|
|
$this->smarty->assign("currentUserId",$current_user->id); |
145
|
|
|
$this->smarty->assign("CURRENT_USER_EMAIL",$current_user->email1); |
146
|
|
|
$this->smarty->assign("currentUserName",$current_user->name); |
147
|
|
|
$this->smarty->assign('yuiPath', 'modules/Emails/javascript/yui-ext/'); |
148
|
|
|
$this->smarty->assign('app_strings', $app_strings); |
149
|
|
|
$this->smarty->assign('mod_strings', $mod_strings); |
150
|
|
|
$this->smarty->assign('theme', $theme); |
151
|
|
|
$this->smarty->assign('sugar_config', $sugar_config); |
152
|
|
|
$this->smarty->assign('is_admin', $current_user->is_admin); |
153
|
|
|
$this->smarty->assign('sugar_version', $sugar_version); |
154
|
|
|
$this->smarty->assign('sugar_flavor', $sugar_flavor); |
155
|
|
|
$this->smarty->assign('current_language', $current_language); |
156
|
|
|
$this->smarty->assign('server_unique_key', $server_unique_key); |
157
|
|
|
$this->smarty->assign('qcModules', json_encode($QCAvailableModules)); |
158
|
|
|
$extAllDebugValue = "ext-all.js"; |
159
|
|
|
$this->smarty->assign('extFileName', $extAllDebugValue); |
160
|
|
|
|
161
|
|
|
// settings: general |
162
|
|
|
$e2UserPreferences = $this->getUserPrefsJS(); |
163
|
|
|
$emailSettings = $e2UserPreferences['emailSettings']; |
164
|
|
|
|
165
|
|
|
/////////////////////////////////////////////////////////////////////// |
166
|
|
|
//// USER SETTINGS |
167
|
|
|
// settings: accounts |
168
|
|
|
|
169
|
|
|
$cuDatePref = $current_user->getUserDateTimePreferences(); |
170
|
|
|
$this->smarty->assign('dateFormat', $cuDatePref['date']); |
171
|
|
|
$this->smarty->assign('dateFormatExample', str_replace(array("Y", "m", "d"), array("yyyy", "mm", "dd"), $cuDatePref['date'])); |
172
|
|
|
$this->smarty->assign('calFormat', $timedate->get_cal_date_format()); |
173
|
|
|
$this->smarty->assign('TIME_FORMAT', $timedate->get_user_time_format()); |
174
|
|
|
|
175
|
|
|
$ieAccounts = $ie->retrieveByGroupId($current_user->id); |
176
|
|
|
$ieAccountsOptions = "<option value=''>{$app_strings['LBL_NONE']}</option>\n"; |
177
|
|
|
|
178
|
|
|
foreach($ieAccounts as $k => $v) { |
179
|
|
|
$disabled = (!$v->is_personal) ? "DISABLED" : ""; |
180
|
|
|
$group = (!$v->is_personal) ? $app_strings['LBL_EMAIL_GROUP']."." : ""; |
181
|
|
|
$ieAccountsOptions .= "<option value='{$v->id}' $disabled>{$group}{$v->name}</option>\n"; |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
$this->smarty->assign('ieAccounts', $ieAccountsOptions); |
185
|
|
|
$this->smarty->assign('rollover', $this->rolloverStyle); |
186
|
|
|
|
187
|
|
|
$protocol = filterInboundEmailPopSelection($app_list_strings['dom_email_server_type']); |
188
|
|
|
$this->smarty->assign('PROTOCOL', get_select_options_with_id($protocol, '')); |
189
|
|
|
$this->smarty->assign('MAIL_SSL_OPTIONS', get_select_options_with_id($app_list_strings['email_settings_for_ssl'], '')); |
190
|
|
|
$this->smarty->assign('ie_mod_strings', return_module_language($current_language, 'InboundEmail')); |
191
|
|
|
|
192
|
|
|
$charsetSelectedValue = isset($emailSettings['defaultOutboundCharset']) ? $emailSettings['defaultOutboundCharset'] : false; |
193
|
|
|
if (!$charsetSelectedValue) { |
194
|
|
|
$charsetSelectedValue = $current_user->getPreference('default_export_charset', 'global'); |
195
|
|
|
if (!$charsetSelectedValue) { |
196
|
|
|
$charsetSelectedValue = $locale->getPrecedentPreference('default_email_charset'); |
197
|
|
|
} |
198
|
|
|
} |
199
|
|
|
$charset = array( |
200
|
|
|
'options' => $locale->getCharsetSelect(), |
201
|
|
|
'selected' => $charsetSelectedValue, |
202
|
|
|
); |
203
|
|
|
$this->smarty->assign('charset', $charset); |
204
|
|
|
|
205
|
|
|
$emailCheckInterval = array('options' => $app_strings['LBL_EMAIL_CHECK_INTERVAL_DOM'], 'selected' => $emailSettings['emailCheckInterval']); |
206
|
|
|
$this->smarty->assign('emailCheckInterval', $emailCheckInterval); |
207
|
|
|
$this->smarty->assign('attachmentsSearchOptions', $app_list_strings['checkbox_dom']); |
208
|
|
|
$this->smarty->assign('sendPlainTextChecked', ($emailSettings['sendPlainText'] == 1) ? 'CHECKED' : ''); |
209
|
|
|
$this->smarty->assign('showNumInList', get_select_options_with_id($app_list_strings['email_settings_num_dom'], $emailSettings['showNumInList'])); |
210
|
|
|
|
211
|
|
|
//// END USER SETTINGS |
212
|
|
|
/////////////////////////////////////////////////////////////////////// |
213
|
|
|
|
214
|
|
|
/////////////////////////////////////////////////////////////////////// |
215
|
|
|
//// SIGNATURES |
216
|
|
|
$prependSignature = ($current_user->getPreference('signature_prepend')) ? 'true' : 'false'; |
217
|
|
|
$defsigID = $current_user->getPreference('signature_default'); |
218
|
|
|
$this->smarty->assign('signatures', $current_user->getSignatures(false, $defsigID)); |
219
|
|
|
$this->smarty->assign('signaturesSettings', $current_user->getSignatures(false, $defsigID, false)); |
220
|
|
|
$signatureButtons = $current_user->getSignatureButtons('SUGAR.email2.settings.createSignature', !empty($defsigID)); |
221
|
|
|
if (!empty($defsigID)) { |
222
|
|
|
$signatureButtons = $signatureButtons . '<span name="delete_sig" id="delete_sig" style="visibility:inherit;"><input class="button" onclick="javascript:SUGAR.email2.settings.deleteSignature();" value="'.$app_strings['LBL_EMAIL_DELETE'].'" type="button" tabindex="392"> |
223
|
|
|
</span>'; |
224
|
|
|
} else { |
225
|
|
|
$signatureButtons = $signatureButtons . '<span name="delete_sig" id="delete_sig" style="visibility:hidden;"><input class="button" onclick="javascript:SUGAR.email2.settings.deleteSignature();" value="'.$app_strings['LBL_EMAIL_DELETE'].'" type="button" tabindex="392"> |
226
|
|
|
</span>'; |
227
|
|
|
} |
228
|
|
|
$this->smarty->assign('signatureButtons', $signatureButtons); |
229
|
|
|
$this->smarty->assign('signaturePrepend', $prependSignature == 'true' ? 'CHECKED' : ''); |
230
|
|
|
//// END SIGNATURES |
231
|
|
|
/////////////////////////////////////////////////////////////////////// |
232
|
|
|
|
233
|
|
|
/////////////////////////////////////////////////////////////////////// |
234
|
|
|
//// EMAIL TEMPLATES |
235
|
|
|
$email_templates_arr = $this->getEmailTemplatesArray(); |
236
|
|
|
natcasesort($email_templates_arr); |
237
|
|
|
$this->smarty->assign('EMAIL_TEMPLATE_OPTIONS', get_select_options_with_id($email_templates_arr, '')); |
238
|
|
|
//// END EMAIL TEMPLATES |
239
|
|
|
/////////////////////////////////////////////////////////////////////// |
240
|
|
|
|
241
|
|
|
/////////////////////////////////////////////////////////////////////// |
242
|
|
|
//// FOLDERS & TreeView |
243
|
|
|
$this->smarty->assign('groupUserOptions', $ie->getGroupsWithSelectOptions(array('' => $app_strings['LBL_EMAIL_CREATE_NEW']))); |
244
|
|
|
|
245
|
|
|
$tree = $this->getMailboxNodes(); |
246
|
|
|
|
247
|
|
|
// preloaded folder |
248
|
|
|
$preloadFolder = 'lazyLoadFolder = '; |
249
|
|
|
$focusFolderSerial = $current_user->getPreference('focusFolder', 'Emails'); |
250
|
|
|
if(!empty($focusFolderSerial)) { |
251
|
|
|
$focusFolder = unserialize($focusFolderSerial); |
252
|
|
|
//$focusFolder['ieId'], $focusFolder['folder'] |
253
|
|
|
$preloadFolder .= json_encode($focusFolder).";"; |
254
|
|
|
} else { |
255
|
|
|
$preloadFolder .= "new Object();"; |
256
|
|
|
} |
257
|
|
|
//// END FOLDERS |
258
|
|
|
/////////////////////////////////////////////////////////////////////// |
259
|
|
|
|
260
|
|
|
$out = ""; |
261
|
|
|
$out .= $this->smarty->fetch("modules/Emails/templates/_baseEmail.tpl"); |
262
|
|
|
$out .= $tree->generate_header(); |
263
|
|
|
$out .= $tree->generateNodesNoInit(true, 'email2treeinit'); |
264
|
|
|
$out .=<<<eoq |
265
|
|
|
<script type="text/javascript" language="javascript"> |
266
|
|
|
|
267
|
|
|
var loader = new YAHOO.util.YUILoader({ |
268
|
|
|
require : [ |
269
|
|
|
"layout", "element", "tabview", "menu", |
270
|
|
|
"cookie", "sugarwidgets" |
271
|
|
|
], |
272
|
|
|
loadOptional: true, |
273
|
|
|
skin: { base: 'blank', defaultSkin: '' }, |
274
|
|
|
onSuccess: email2init, |
275
|
|
|
allowRollup: true, |
276
|
|
|
base: "include/javascript/yui/build/" |
277
|
|
|
}); |
278
|
|
|
loader.addModule({ |
279
|
|
|
name :"sugarwidgets", |
280
|
|
|
type : "js", |
281
|
|
|
fullpath: "include/javascript/sugarwidgets/SugarYUIWidgets.js", |
282
|
|
|
varName: "YAHOO.SUGAR", |
283
|
|
|
requires: ["datatable", "dragdrop", "treeview", "tabview", "calendar"] |
284
|
|
|
}); |
285
|
|
|
loader.insert(); |
286
|
|
|
|
287
|
|
|
{$preloadFolder}; |
288
|
|
|
|
289
|
|
|
</script> |
290
|
|
|
eoq; |
291
|
|
|
|
292
|
|
|
|
293
|
|
|
return $out; |
294
|
|
|
} |
295
|
|
|
|
296
|
|
|
/** |
297
|
|
|
* Generate the frame needed for the quick compose email UI. This frame is loaded dynamically |
298
|
|
|
* by an ajax call. |
299
|
|
|
* |
300
|
|
|
* @return JSON An object containing html markup and js script variables. |
301
|
|
|
*/ |
302
|
|
|
function displayQuickComposeEmailFrame() |
303
|
|
|
{ |
304
|
|
|
$this->preflightUserCache(); |
305
|
|
|
|
306
|
|
|
$this->_generateComposeConfigData('email_compose_light'); |
307
|
|
|
$javascriptOut = $this->smarty->fetch("modules/Emails/templates/_baseConfigData.tpl"); |
308
|
|
|
|
309
|
|
|
$divOut = $this->smarty->fetch("modules/Emails/templates/overlay.tpl"); |
310
|
|
|
$divOut .= $this->smarty->fetch("modules/Emails/templates/addressSearchContent.tpl"); |
311
|
|
|
|
312
|
|
|
$outData = array('jsData' => $javascriptOut,'divData'=> $divOut); |
313
|
|
|
$out = json_encode($outData); |
314
|
|
|
return $out; |
315
|
|
|
} |
316
|
|
|
|
317
|
|
|
/** |
318
|
|
|
* Load the modules from the metadata file and include in a custom one if it exists |
319
|
|
|
* |
320
|
|
|
* @return array |
321
|
|
|
*/ |
322
|
|
|
protected function _loadQuickCreateModules() |
323
|
|
|
{ |
324
|
|
|
$QCAvailableModules = array(); |
325
|
|
|
$QCModules = array(); |
326
|
|
|
|
327
|
|
|
include('modules/Emails/metadata/qcmodulesdefs.php'); |
328
|
|
|
if (file_exists('custom/modules/Emails/metadata/qcmodulesdefs.php')) { |
329
|
|
|
include('custom/modules/Emails/metadata/qcmodulesdefs.php'); |
330
|
|
|
} |
331
|
|
|
|
332
|
|
|
foreach($QCModules as $module) { |
333
|
|
|
$seed = SugarModule::get($module)->loadBean(); |
334
|
|
|
if ( ( $seed instanceOf SugarBean ) && $seed->ACLAccess('edit') ) { |
335
|
|
|
$QCAvailableModules[] = $module; |
336
|
|
|
} |
337
|
|
|
} |
338
|
|
|
|
339
|
|
|
return $QCAvailableModules; |
340
|
|
|
} |
341
|
|
|
|
342
|
|
|
/** |
343
|
|
|
* Given an email link url (eg. index.php?action=Compose&parent_type=Contacts...) break up the |
344
|
|
|
* request components and create a compose package that can be used by the quick compose UI. The |
345
|
|
|
* result is typically passed into the js call SUGAR.quickCompose.init which initalizes the quick compose |
346
|
|
|
* UI. |
347
|
|
|
* |
348
|
|
|
* @param String $emailLinkUrl |
349
|
|
|
* @return JSON Object containing the composePackage and full link url |
350
|
|
|
*/ |
351
|
|
|
function generateComposePackageForQuickCreateFromComposeUrl($emailLinkUrl, $lazyLoad=false) |
352
|
|
|
{ |
353
|
|
|
$composeData = explode("&",$emailLinkUrl); |
354
|
|
|
$a_composeData = array(); |
355
|
|
|
foreach ($composeData as $singleRequest) |
356
|
|
|
{ |
357
|
|
|
$tmp = explode("=",$singleRequest); |
358
|
|
|
$a_composeData[$tmp[0]] = urldecode($tmp[1]); |
359
|
|
|
} |
360
|
|
|
|
361
|
|
|
return $this->generateComposePackageForQuickCreate($a_composeData,$emailLinkUrl, $lazyLoad); |
362
|
|
|
} |
363
|
|
|
/** |
364
|
|
|
* Generate the composePackage for the quick compose email UI. The package contains |
365
|
|
|
* key/value pairs generated by the Compose.php file which are then set into the |
366
|
|
|
* quick compose email UI (eg. to addr, parent id, parent type, etc) |
367
|
|
|
* |
368
|
|
|
* @param Array $composeData Associative array read and processed by generateComposeDataPackage. |
369
|
|
|
* @param String $fullLinkUrl A link that contains all pertinant information so the user can be |
370
|
|
|
* directed to the full compose screen if needed |
371
|
|
|
* @param SugarBean $bean Optional - the parent object bean with data |
372
|
|
|
* @return JSON Object containg composePackage and fullLinkUrl |
373
|
|
|
*/ |
374
|
|
|
function generateComposePackageForQuickCreate($composeData,$fullLinkUrl, $lazyLoad=false, $bean = null) |
375
|
|
|
{ |
376
|
|
|
$_REQUEST['forQuickCreate'] = true; |
377
|
|
|
|
378
|
|
|
if(!$lazyLoad){ |
379
|
|
|
require_once('modules/Emails/Compose.php'); |
380
|
|
|
$composePackage = generateComposeDataPackage($composeData,FALSE, $bean); |
|
|
|
|
381
|
|
|
}else{ |
382
|
|
|
$composePackage = $composeData; |
383
|
|
|
} |
384
|
|
|
|
385
|
|
|
// JSON object is passed into the function defined within the a href onclick event |
386
|
|
|
// which is delimeted by '. Need to escape all single quotes and &, <, > |
387
|
|
|
// but not double quotes since json would escape them |
388
|
|
|
foreach ($composePackage as $key => $singleCompose) |
|
|
|
|
389
|
|
|
{ |
390
|
|
|
if (is_string($singleCompose)) |
391
|
|
|
$composePackage[$key] = str_replace(" ", " ", from_html($singleCompose)); |
392
|
|
|
} |
393
|
|
|
|
394
|
|
|
$quickComposeOptions = array('fullComposeUrl' => $fullLinkUrl,'composePackage' => $composePackage); |
395
|
|
|
|
396
|
|
|
$j_quickComposeOptions = JSON::encode($quickComposeOptions, false ,true); |
397
|
|
|
|
398
|
|
|
|
399
|
|
|
return $j_quickComposeOptions; |
400
|
|
|
} |
401
|
|
|
|
402
|
|
|
/** |
403
|
|
|
* Generate the config data needed for the Full Compose UI and the Quick Compose UI. The set of config data |
404
|
|
|
* returned is the minimum set needed by the quick compose UI. |
405
|
|
|
* |
406
|
|
|
* @param String $type Drives which tinyMCE options will be included. |
407
|
|
|
*/ |
408
|
|
|
function _generateComposeConfigData($type = "email_compose_light" ) |
409
|
|
|
{ |
410
|
|
|
global $app_list_strings,$current_user, $app_strings, $mod_strings,$current_language,$locale; |
411
|
|
|
|
412
|
|
|
//Link drop-downs |
413
|
|
|
$parent_types = $app_list_strings['record_type_display']; |
414
|
|
|
$disabled_parent_types = ACLController::disabledModuleList($parent_types, false, 'list'); |
415
|
|
|
|
416
|
|
|
foreach($disabled_parent_types as $disabled_parent_type) { |
417
|
|
|
unset($parent_types[$disabled_parent_type]); |
418
|
|
|
} |
419
|
|
|
asort($parent_types); |
420
|
|
|
$linkBeans = json_encode(get_select_options_with_id($parent_types, '')); |
421
|
|
|
|
422
|
|
|
//TinyMCE Config |
423
|
|
|
require_once("include/SugarTinyMCE.php"); |
424
|
|
|
$tiny = new SugarTinyMCE(); |
425
|
|
|
$tinyConf = $tiny->getConfig($type); |
426
|
|
|
|
427
|
|
|
//Generate Language Packs |
428
|
|
|
$lang = "var app_strings = new Object();\n"; |
429
|
|
|
foreach($app_strings as $k => $v) { |
430
|
|
|
if(strpos($k, 'LBL_EMAIL_') !== false) { |
431
|
|
|
$lang .= "app_strings.{$k} = '{$v}';\n"; |
432
|
|
|
} |
433
|
|
|
} |
434
|
|
|
//Get the email mod strings but don't use the global variable as this may be overridden by |
435
|
|
|
//other modules when the quick create is rendered. |
436
|
|
|
$email_mod_strings = return_module_language($current_language,'Emails'); |
437
|
|
|
$modStrings = "var mod_strings = new Object();\n"; |
438
|
|
|
foreach($email_mod_strings as $k => $v) { |
|
|
|
|
439
|
|
|
$v = str_replace("'", "\'", $v); |
440
|
|
|
$modStrings .= "mod_strings.{$k} = '{$v}';\n"; |
441
|
|
|
} |
442
|
|
|
$lang .= "\n\n{$modStrings}\n"; |
443
|
|
|
|
444
|
|
|
//Grab the Inboundemail language pack |
445
|
|
|
$ieModStrings = "var ie_mod_strings = new Object();\n"; |
446
|
|
|
$ie_mod_strings = return_module_language($current_language,'InboundEmail'); |
447
|
|
|
foreach($ie_mod_strings as $k => $v) { |
|
|
|
|
448
|
|
|
$v = str_replace("'", "\'", $v); |
449
|
|
|
$ieModStrings .= "ie_mod_strings.{$k} = '{$v}';\n"; |
450
|
|
|
} |
451
|
|
|
$lang .= "\n\n{$ieModStrings}\n"; |
452
|
|
|
|
453
|
|
|
$this->smarty->assign('linkBeans', $linkBeans); |
454
|
|
|
$this->smarty->assign('linkBeansOptions', $parent_types); |
455
|
|
|
$this->smarty->assign('tinyMCE', $tinyConf); |
456
|
|
|
$this->smarty->assign('lang', $lang); |
457
|
|
|
$this->smarty->assign('app_strings', $app_strings); |
458
|
|
|
$this->smarty->assign('mod_strings', $email_mod_strings); |
459
|
|
|
$ie1 = new InboundEmail(); |
460
|
|
|
|
461
|
|
|
//Signatures |
462
|
|
|
$defsigID = $current_user->getPreference('signature_default'); |
463
|
|
|
$defaultSignature = $current_user->getDefaultSignature(); |
464
|
|
|
$sigJson = !empty($defaultSignature) ? json_encode(array($defaultSignature['id'] => from_html($defaultSignature['signature_html']))) : "new Object()"; |
465
|
|
|
$this->smarty->assign('defaultSignature', $sigJson); |
466
|
|
|
$this->smarty->assign('signatureDefaultId', (isset($defaultSignature['id'])) ? $defaultSignature['id'] : ""); |
467
|
|
|
//User Preferences |
468
|
|
|
$this->smarty->assign('userPrefs', json_encode($this->getUserPrefsJS())); |
469
|
|
|
|
470
|
|
|
//Get the users default outbound id |
471
|
|
|
$defaultOutID = $ie1->getUsersDefaultOutboundServerId($current_user); |
472
|
|
|
$this->smarty->assign('defaultOutID', $defaultOutID); |
473
|
|
|
|
474
|
|
|
//Character Set |
475
|
|
|
$charsets = json_encode($locale->getCharsetSelect()); |
476
|
|
|
$this->smarty->assign('emailCharsets', $charsets); |
477
|
|
|
|
478
|
|
|
//Relateable List of People for address book search |
479
|
|
|
//#20776 jchi |
480
|
|
|
$peopleTables = array("users", |
481
|
|
|
"contacts", |
482
|
|
|
"leads", |
483
|
|
|
"prospects", |
484
|
|
|
"accounts"); |
485
|
|
|
$filterPeopleTables = array(); |
486
|
|
|
global $app_list_strings, $app_strings; |
487
|
|
|
$filterPeopleTables['LBL_DROPDOWN_LIST_ALL'] = $app_strings['LBL_DROPDOWN_LIST_ALL']; |
488
|
|
|
foreach($peopleTables as $table) { |
489
|
|
|
$module = ucfirst($table); |
490
|
|
|
$class = substr($module, 0, strlen($module) - 1); |
491
|
|
|
require_once("modules/{$module}/{$class}.php"); |
492
|
|
|
$person = new $class(); |
493
|
|
|
|
494
|
|
|
if (!$person->ACLAccess('list')) continue; |
495
|
|
|
$filterPeopleTables[$person->table_name] = $app_list_strings['moduleList'][$person->module_dir]; |
496
|
|
|
} |
497
|
|
|
$this->smarty->assign('listOfPersons' , get_select_options_with_id($filterPeopleTables,'')); |
498
|
|
|
|
499
|
|
|
} |
500
|
|
|
|
501
|
|
|
|
502
|
|
|
|
503
|
|
|
//// END CORE |
504
|
|
|
/////////////////////////////////////////////////////////////////////////// |
505
|
|
|
|
506
|
|
|
/////////////////////////////////////////////////////////////////////////// |
507
|
|
|
//// ADDRESS BOOK |
508
|
|
|
/** |
509
|
|
|
* Retrieves all relationship metadata for a user's address book |
510
|
|
|
* @return array |
511
|
|
|
*/ |
512
|
|
|
function getContacts() { |
513
|
|
|
global $current_user; |
514
|
|
|
|
515
|
|
|
$q = "SELECT * FROM address_book WHERE assigned_user_id = '{$current_user->id}' ORDER BY bean DESC"; |
516
|
|
|
$r = $this->db->query($q); |
517
|
|
|
|
518
|
|
|
$ret = array(); |
519
|
|
|
|
520
|
|
|
while($a = $this->db->fetchByAssoc($r)) { |
521
|
|
|
$ret[$a['bean_id']] = array( |
522
|
|
|
'id' => $a['bean_id'], |
523
|
|
|
'module' => $a['bean'], |
524
|
|
|
); |
525
|
|
|
} |
526
|
|
|
|
527
|
|
|
return $ret; |
528
|
|
|
} |
529
|
|
|
|
530
|
|
|
/** |
531
|
|
|
* Saves changes to a user's address book |
532
|
|
|
* @param array contacts |
533
|
|
|
*/ |
534
|
|
|
function setContacts($contacts) { |
535
|
|
|
global $current_user; |
536
|
|
|
|
537
|
|
|
$oldContacts = $this->getContacts(); |
538
|
|
|
|
539
|
|
|
foreach($contacts as $cid => $contact) { |
540
|
|
|
if(!in_array($contact['id'], $oldContacts)) { |
541
|
|
|
$q = "INSERT INTO address_book (assigned_user_id, bean, bean_id) VALUES ('{$current_user->id}', '{$contact['module']}', '{$contact['id']}')"; |
542
|
|
|
$r = $this->db->query($q, true); |
543
|
|
|
} |
544
|
|
|
} |
545
|
|
|
} |
546
|
|
|
|
547
|
|
|
/** |
548
|
|
|
* Removes contacts from the user's address book |
549
|
|
|
* @param array ids |
550
|
|
|
*/ |
551
|
|
|
function removeContacts($ids) { |
552
|
|
|
global $current_user; |
553
|
|
|
|
554
|
|
|
$concat = ""; |
555
|
|
|
|
556
|
|
|
foreach($ids as $id) { |
557
|
|
|
if(!empty($concat)) |
558
|
|
|
$concat .= ", "; |
559
|
|
|
|
560
|
|
|
$concat .= "'{$id}'"; |
561
|
|
|
} |
562
|
|
|
|
563
|
|
|
$q = "DELETE FROM address_book WHERE assigned_user_id = '{$current_user->id}' AND bean_id IN ({$concat})"; |
564
|
|
|
$r = $this->db->query($q); |
565
|
|
|
} |
566
|
|
|
|
567
|
|
|
/** |
568
|
|
|
* saves editted Contact info |
569
|
|
|
* @param string $str JSON serialized object |
570
|
|
|
*/ |
571
|
|
|
function saveContactEdit($str) { |
572
|
|
|
|
573
|
|
|
$json = getJSONobj(); |
574
|
|
|
|
575
|
|
|
$str = from_html($str); |
576
|
|
|
$obj = $json->decode($str); |
577
|
|
|
|
578
|
|
|
$contact = new Contact(); |
579
|
|
|
$contact->retrieve($obj['contact_id']); |
580
|
|
|
$contact->first_name = $obj['contact_first_name']; |
581
|
|
|
$contact->last_name = $obj['contact_last_name']; |
582
|
|
|
$contact->save(); |
583
|
|
|
|
584
|
|
|
// handle email address changes |
585
|
|
|
$addresses = array(); |
586
|
|
|
|
587
|
|
|
foreach($obj as $k => $req) { |
|
|
|
|
588
|
|
|
if(strpos($k, 'emailAddress') !== false) { |
589
|
|
|
$addresses[$k] = $req; |
590
|
|
|
} |
591
|
|
|
} |
592
|
|
|
|
593
|
|
|
// prefill some REQUEST vars for emailAddress save |
594
|
|
|
$_REQUEST['emailAddressOptOutFlag'] = $obj['optOut']; |
595
|
|
|
$_REQUEST['emailAddressInvalidFlag'] = $obj['invalid']; |
596
|
|
|
$contact->emailAddress->save($obj['contact_id'], 'Contacts', $addresses, $obj['primary'], ''); |
597
|
|
|
} |
598
|
|
|
|
599
|
|
|
/** |
600
|
|
|
* Prepares the Edit Contact mini-form via template assignment |
601
|
|
|
* @param string id ID of contact in question |
602
|
|
|
* @param string module Module in focus |
603
|
|
|
* @return array |
604
|
|
|
*/ |
605
|
|
|
function getEditContact($id, $module) { |
606
|
|
|
global $app_strings; |
607
|
|
|
|
608
|
|
|
|
609
|
|
|
if(!class_exists("Contact")) { |
|
|
|
|
610
|
|
|
|
611
|
|
|
} |
612
|
|
|
|
613
|
|
|
$contact = new Contact(); |
614
|
|
|
$contact->retrieve($_REQUEST['id']); |
615
|
|
|
$ret = array(); |
616
|
|
|
|
617
|
|
|
if($contact->ACLAccess('edit')) { |
618
|
|
|
$contactMeta = array(); |
619
|
|
|
$contactMeta['id'] = $contact->id; |
620
|
|
|
$contactMeta['module'] = $contact->module_dir; |
621
|
|
|
$contactMeta['first_name'] = $contact->first_name; |
622
|
|
|
$contactMeta['last_name'] = $contact->last_name; |
623
|
|
|
|
624
|
|
|
$this->smarty->assign("app_strings", $app_strings); |
625
|
|
|
$this->smarty->assign("contact_strings", return_module_language($_SESSION['authenticated_user_language'], 'Contacts')); |
626
|
|
|
$this->smarty->assign("contact", $contactMeta); |
627
|
|
|
|
628
|
|
|
$ea = new SugarEmailAddress(); |
629
|
|
|
$newEmail = $ea->getEmailAddressWidgetEditView($id, $module, true); |
630
|
|
|
$this->smarty->assign("emailWidget", $newEmail['html']); |
631
|
|
|
|
632
|
|
|
$ret['form'] = $this->smarty->fetch("modules/Emails/templates/editContact.tpl"); |
633
|
|
|
$ret['prefillData'] = $newEmail['prefillData']; |
634
|
|
|
} else { |
635
|
|
|
$id = ""; |
636
|
|
|
$ret['form'] = $app_strings['LBL_EMAIL_ERROR_NO_ACCESS']; |
637
|
|
|
$ret['prefillData'] = '{}'; |
638
|
|
|
} |
639
|
|
|
|
640
|
|
|
$ret['id'] = $id; |
641
|
|
|
$ret['contactName'] = $contact->full_name; |
642
|
|
|
|
643
|
|
|
return $ret; |
644
|
|
|
} |
645
|
|
|
|
646
|
|
|
|
647
|
|
|
/** |
648
|
|
|
* Retrieves a concatenated list of contacts, those with assigned_user_id = user's id and those in the address_book |
649
|
|
|
* table |
650
|
|
|
* @param array $contacts Array of contact types -> IDs |
651
|
|
|
* @param object $user User in focus |
652
|
|
|
* @return array |
653
|
|
|
*/ |
654
|
|
|
function getUserContacts($contacts, $user=null) { |
655
|
|
|
|
656
|
|
|
global $current_user; |
657
|
|
|
global $locale; |
658
|
|
|
|
659
|
|
|
if(empty($user)) { |
660
|
|
|
$user = $current_user; |
661
|
|
|
} |
662
|
|
|
|
663
|
|
|
$emailAddress = new SugarEmailAddress(); |
664
|
|
|
$ret = array(); |
665
|
|
|
|
666
|
|
|
$union = ''; |
667
|
|
|
|
668
|
|
|
$modules = array(); |
669
|
|
|
foreach($contacts as $contact) { |
670
|
|
|
if(!isset($modules[$contact['module']])) { |
671
|
|
|
$modules[$contact['module']] = array(); |
672
|
|
|
} |
673
|
|
|
$modules[$contact['module']][] = $contact; |
674
|
|
|
} |
675
|
|
|
|
676
|
|
|
foreach($modules as $module => $contacts) { |
677
|
|
|
if(!empty($union)) { |
678
|
|
|
$union .= " UNION ALL "; |
679
|
|
|
} |
680
|
|
|
|
681
|
|
|
$table = strtolower($module); |
682
|
|
|
$idsSerial = ''; |
683
|
|
|
|
684
|
|
|
foreach($contacts as $contact) { |
685
|
|
|
if(!empty($idsSerial)) { |
686
|
|
|
$idsSerial .= ","; |
687
|
|
|
} |
688
|
|
|
$idsSerial .= "'{$contact['id']}'"; |
689
|
|
|
} |
690
|
|
|
|
691
|
|
|
$union .= "(SELECT id, first_name, last_name, title, '{$module}' module FROM {$table} WHERE id IN({$idsSerial}) AND deleted = 0 )"; |
692
|
|
|
} |
693
|
|
|
if(!empty($union)) { |
694
|
|
|
$union .= " ORDER BY last_name"; |
695
|
|
|
} |
696
|
|
|
|
697
|
|
|
$r = $user->db->query($union); |
698
|
|
|
|
699
|
|
|
//_pp($union); |
700
|
|
|
|
701
|
|
|
while($a = $user->db->fetchByAssoc($r)) { |
702
|
|
|
$c = array(); |
703
|
|
|
|
704
|
|
|
$c['name'] = $locale->getLocaleFormattedName($a['first_name'], "<b>{$a['last_name']}</b>", '', $a['title'], '', $user); |
705
|
|
|
$c['id'] = $a['id']; |
706
|
|
|
$c['module'] = $a['module']; |
707
|
|
|
$c['email'] = $emailAddress->getAddressesByGUID($a['id'], $a['module']); |
708
|
|
|
$ret[$a['id']] = $c; |
709
|
|
|
} |
710
|
|
|
|
711
|
|
|
return $ret; |
712
|
|
|
} |
713
|
|
|
//// END ADDRESS BOOK |
714
|
|
|
/////////////////////////////////////////////////////////////////////////// |
715
|
|
|
|
716
|
|
|
|
717
|
|
|
/////////////////////////////////////////////////////////////////////////// |
718
|
|
|
//// EMAIL 2.0 Preferences |
719
|
|
|
function getUserPrefsJS() { |
720
|
|
|
global $current_user; |
721
|
|
|
global $locale; |
722
|
|
|
|
723
|
|
|
// sort order per mailbox view |
724
|
|
|
$sortSerial = $current_user->getPreference('folderSortOrder', 'Emails'); |
725
|
|
|
$sortArray = array(); |
726
|
|
|
if(!empty($sortSerial)) { |
727
|
|
|
$sortArray = unserialize($sortSerial); |
728
|
|
|
} |
729
|
|
|
|
730
|
|
|
// treeview collapsed/open states |
731
|
|
|
$folderStateSerial = $current_user->getPreference('folderOpenState', 'Emails'); |
732
|
|
|
$folderStates = array(); |
733
|
|
|
if(!empty($folderStateSerial)) { |
734
|
|
|
$folderStates = unserialize($folderStateSerial); |
735
|
|
|
} |
736
|
|
|
|
737
|
|
|
// subscribed accounts |
738
|
|
|
$showFolders = unserialize(base64_decode($current_user->getPreference('showFolders', 'Emails'))); |
739
|
|
|
|
740
|
|
|
// general settings |
741
|
|
|
$emailSettings = $current_user->getPreference('emailSettings', 'Emails'); |
742
|
|
|
|
743
|
|
|
if(empty($emailSettings)) { |
744
|
|
|
$emailSettings = array(); |
745
|
|
|
$emailSettings['emailCheckInterval'] = -1; |
746
|
|
|
$emailSettings['autoImport'] = ''; |
747
|
|
|
$emailSettings['alwaysSaveOutbound'] = '1'; |
748
|
|
|
$emailSettings['sendPlainText'] = ''; |
749
|
|
|
$emailSettings['defaultOutboundCharset'] = $GLOBALS['sugar_config']['default_email_charset']; |
750
|
|
|
$emailSettings['showNumInList'] = 20; |
751
|
|
|
} |
752
|
|
|
|
753
|
|
|
// focus folder |
754
|
|
|
$focusFolder = $current_user->getPreference('focusFolder', 'Emails'); |
755
|
|
|
$focusFolder = !empty($focusFolder) ? unserialize($focusFolder) : array(); |
756
|
|
|
|
757
|
|
|
// unread only flag |
758
|
|
|
$showUnreadOnly = $current_user->getPreference('showUnreadOnly', 'Emails'); |
759
|
|
|
|
760
|
|
|
$listViewSort = array( |
761
|
|
|
"sortBy" => 'date', |
762
|
|
|
"sortDirection" => 'DESC', |
763
|
|
|
); |
764
|
|
|
|
765
|
|
|
// signature prefs |
766
|
|
|
$signaturePrepend = $current_user->getPreference('signature_prepend') ? 'true' : 'false'; |
767
|
|
|
$signatureDefault = $current_user->getPreference('signature_default'); |
768
|
|
|
$signatures = array( |
769
|
|
|
'signature_prepend' => $signaturePrepend, |
770
|
|
|
'signature_default' => $signatureDefault |
771
|
|
|
); |
772
|
|
|
|
773
|
|
|
|
774
|
|
|
// current_user |
775
|
|
|
$user = array( |
776
|
|
|
'emailAddresses' => $current_user->emailAddress->getAddressesByGUID($current_user->id, 'Users'), |
777
|
|
|
'full_name' => from_html($current_user->full_name), |
778
|
|
|
); |
779
|
|
|
|
780
|
|
|
$userPreferences = array(); |
781
|
|
|
$userPreferences['sort'] = $sortArray; |
782
|
|
|
$userPreferences['folderStates'] = $folderStates; |
783
|
|
|
$userPreferences['showFolders'] = $showFolders; |
784
|
|
|
$userPreferences['emailSettings'] = $emailSettings; |
785
|
|
|
$userPreferences['focusFolder'] = $focusFolder; |
786
|
|
|
$userPreferences['showUnreadOnly'] = $showUnreadOnly; |
787
|
|
|
$userPreferences['listViewSort'] = $listViewSort; |
788
|
|
|
$userPreferences['signatures'] = $signatures; |
789
|
|
|
$userPreferences['current_user'] = $user; |
790
|
|
|
return $userPreferences; |
791
|
|
|
} |
792
|
|
|
|
793
|
|
|
|
794
|
|
|
|
795
|
|
|
/////////////////////////////////////////////////////////////////////////// |
796
|
|
|
//// FOLDER FUNCTIONS |
797
|
|
|
|
798
|
|
|
/** |
799
|
|
|
* Creates a new Sugar folder |
800
|
|
|
* @param string $nodeLabel New sugar folder name |
801
|
|
|
* @param string $parentLabel Parent folder name |
|
|
|
|
802
|
|
|
*/ |
803
|
|
|
function saveNewFolder($nodeLabel, $parentId, $isGroup=0) { |
804
|
|
|
global $current_user; |
805
|
|
|
|
806
|
|
|
$this->folder->name = $nodeLabel; |
807
|
|
|
$this->folder->is_group = $isGroup; |
808
|
|
|
$this->folder->parent_folder = ($parentId == 'Home') ? "" : $parentId; |
809
|
|
|
$this->folder->has_child = 0; |
810
|
|
|
$this->folder->created_by = $current_user->id; |
811
|
|
|
$this->folder->modified_by = $current_user->id; |
812
|
|
|
$this->folder->date_modified = $this->folder->date_created = TimeDate::getInstance()->nowDb(); |
813
|
|
|
|
814
|
|
|
$this->folder->save(); |
815
|
|
|
return array( |
816
|
|
|
'action' => 'newFolderSave', |
817
|
|
|
'id' => $this->folder->id, |
818
|
|
|
'name' => $this->folder->name, |
819
|
|
|
'is_group' => $this->folder->is_group, |
820
|
|
|
'is_dynamic' => $this->folder->is_dynamic |
821
|
|
|
); |
822
|
|
|
} |
823
|
|
|
|
824
|
|
|
/** |
825
|
|
|
* Saves user sort prefernces |
826
|
|
|
*/ |
827
|
|
|
function saveListViewSortOrder($ieId, $focusFolder, $sortBy, $sortDir) { |
828
|
|
|
global $current_user; |
829
|
|
|
|
830
|
|
|
$sortArray = array(); |
831
|
|
|
|
832
|
|
|
$sortSerial = $current_user->getPreference('folderSortOrder', 'Emails'); |
833
|
|
|
if(!empty($sortSerial)) { |
834
|
|
|
$sortArray = unserialize($sortSerial); |
835
|
|
|
} |
836
|
|
|
|
837
|
|
|
$sortArray[$ieId][$focusFolder]['current']['sort'] = $sortBy; |
838
|
|
|
$sortArray[$ieId][$focusFolder]['current']['direction'] = $sortDir; |
839
|
|
|
$sortSerial = serialize($sortArray); |
840
|
|
|
$current_user->setPreference('folderSortOrder', $sortSerial, '', 'Emails'); |
841
|
|
|
} |
842
|
|
|
|
843
|
|
|
/** |
844
|
|
|
* Stickies folder collapse/open state |
845
|
|
|
*/ |
846
|
|
|
function saveFolderOpenState($focusFolder, $focusFolderOpen) { |
847
|
|
|
global $current_user; |
848
|
|
|
|
849
|
|
|
$folderStateSerial = $current_user->getPreference('folderOpenState', 'Emails'); |
850
|
|
|
$folderStates = array(); |
851
|
|
|
|
852
|
|
|
if(!empty($folderStateSerial)) { |
853
|
|
|
$folderStates = unserialize($folderStateSerial); |
854
|
|
|
} |
855
|
|
|
|
856
|
|
|
$folderStates[$focusFolder] = $focusFolderOpen; |
857
|
|
|
$newFolderStateSerial = serialize($folderStates); |
858
|
|
|
$current_user->setPreference('folderOpenState', $newFolderStateSerial, '', 'Emails'); |
859
|
|
|
} |
860
|
|
|
|
861
|
|
|
/** |
862
|
|
|
* saves a folder's view state |
863
|
|
|
*/ |
864
|
|
|
function saveListView($ieId, $folder) { |
865
|
|
|
global $current_user; |
866
|
|
|
|
867
|
|
|
$saveState = array(); |
868
|
|
|
$saveState['ieId'] = $ieId; |
869
|
|
|
$saveState['folder'] = $folder; |
870
|
|
|
$saveStateSerial = serialize($saveState); |
871
|
|
|
$current_user->setPreference('focusFolder', $saveStateSerial, '', 'Emails'); |
872
|
|
|
} |
873
|
|
|
|
874
|
|
|
/** |
875
|
|
|
* Generates cache folder structure |
876
|
|
|
*/ |
877
|
|
|
function preflightEmailCache($cacheRoot) { |
878
|
|
|
// base |
879
|
|
|
if(!file_exists($cacheRoot)) |
880
|
|
|
mkdir_recursive(clean_path($cacheRoot)); |
881
|
|
|
|
882
|
|
|
// folders |
883
|
|
|
if(!file_exists($cacheRoot."/folders")) |
884
|
|
|
mkdir_recursive(clean_path("{$cacheRoot}/folders")); |
885
|
|
|
|
886
|
|
|
// messages |
887
|
|
|
if(!file_exists($cacheRoot."/messages")) |
888
|
|
|
mkdir_recursive(clean_path("{$cacheRoot}/messages")); |
889
|
|
|
|
890
|
|
|
// attachments |
891
|
|
|
if(!file_exists($cacheRoot."/attachments")) |
892
|
|
|
mkdir_recursive(clean_path("{$cacheRoot}/attachments")); |
893
|
|
|
} |
894
|
|
|
|
895
|
|
|
function deleteEmailCacheForFolders($cacheRoot) { |
896
|
|
|
$filePath = $cacheRoot."/folders/folders.php"; |
897
|
|
|
if (file_exists($filePath)) { |
898
|
|
|
unlink($filePath); |
899
|
|
|
} |
900
|
|
|
} |
901
|
|
|
/////////////////////////////////////////////////////////////////////////// |
902
|
|
|
//// IMAP FUNCTIONS |
903
|
|
|
/** |
904
|
|
|
* Identifies subscribed mailboxes and empties the trash |
905
|
|
|
* @param object $ie InboundEmail |
906
|
|
|
*/ |
907
|
|
|
function emptyTrash(&$ie) { |
908
|
|
|
global $current_user; |
909
|
|
|
|
910
|
|
|
$showFolders = unserialize(base64_decode($current_user->getPreference('showFolders', 'Emails'))); |
911
|
|
|
|
912
|
|
|
if(is_array($showFolders)) { |
913
|
|
|
foreach($showFolders as $ieId) { |
914
|
|
|
if(!empty($ieId)) { |
915
|
|
|
$ie->retrieve($ieId); |
916
|
|
|
$ie->emptyTrash(); |
917
|
|
|
} |
918
|
|
|
} |
919
|
|
|
} |
920
|
|
|
} |
921
|
|
|
|
922
|
|
|
/** |
923
|
|
|
* returns an array of nodes that correspond to IMAP mailboxes. |
924
|
|
|
* @param bool $forceRefresh |
|
|
|
|
925
|
|
|
* @return object TreeView object |
926
|
|
|
*/ |
927
|
|
|
function getMailboxNodes() { |
928
|
|
|
global $sugar_config; |
929
|
|
|
global $current_user; |
930
|
|
|
global $app_strings; |
931
|
|
|
|
932
|
|
|
$tree = new Tree("frameFolders"); |
933
|
|
|
$tree->tree_style= 'include/ytree/TreeView/css/check/tree.css'; |
934
|
|
|
|
935
|
|
|
$nodes = array(); |
936
|
|
|
$ie = new InboundEmail(); |
937
|
|
|
$refreshOffset = $this->cacheTimeouts['folders']; // 5 mins. this will be set via user prefs |
938
|
|
|
|
939
|
|
|
$rootNode = new ExtNode($app_strings['LBL_EMAIL_HOME_FOLDER'], $app_strings['LBL_EMAIL_HOME_FOLDER']); |
940
|
|
|
$rootNode->dynamicloadfunction = ''; |
941
|
|
|
$rootNode->expanded = true; |
942
|
|
|
$rootNode->dynamic_load = true; |
943
|
|
|
$showFolders = unserialize(base64_decode($current_user->getPreference('showFolders', 'Emails'))); |
944
|
|
|
|
945
|
|
|
if(empty($showFolders)) { |
946
|
|
|
$showFolders = array(); |
947
|
|
|
} |
948
|
|
|
|
949
|
|
|
// INBOX NODES |
950
|
|
|
if($current_user->hasPersonalEmail()) { |
951
|
|
|
$personals = $ie->retrieveByGroupId($current_user->id); |
952
|
|
|
|
953
|
|
|
foreach($personals as $k => $personalAccount) { |
954
|
|
|
if(in_array($personalAccount->id, $showFolders)) { |
955
|
|
|
// check for cache value |
956
|
|
|
$cacheRoot = sugar_cached("modules/Emails/{$personalAccount->id}"); |
957
|
|
|
$this->preflightEmailCache($cacheRoot); |
958
|
|
|
|
959
|
|
|
if($this->validCacheFileExists($personalAccount->id, 'folders', "folders.php")) { |
960
|
|
|
$mailboxes = $this->getMailBoxesFromCacheValue($personalAccount); |
961
|
|
|
} else { |
962
|
|
|
$mailboxes = $personalAccount->getMailboxes(); |
963
|
|
|
} |
964
|
|
|
|
965
|
|
|
$acctNode = new ExtNode('Home::' . $personalAccount->name, $personalAccount->name); |
966
|
|
|
$acctNode->dynamicloadfunction = ''; |
967
|
|
|
$acctNode->expanded = false; |
968
|
|
|
$acctNode->set_property('cls', 'ieFolder'); |
969
|
|
|
$acctNode->set_property('ieId', $personalAccount->id); |
970
|
|
|
$acctNode->set_property('protocol', $personalAccount->protocol); |
971
|
|
|
|
972
|
|
|
if(array_key_exists('Home::'.$personalAccount->name, $this->folderStates)) { |
973
|
|
|
if($this->folderStates['Home::'.$personalAccount->name] == 'open') { |
974
|
|
|
$acctNode->expanded = true; |
975
|
|
|
} |
976
|
|
|
} |
977
|
|
|
$acctNode->dynamic_load = true; |
978
|
|
|
|
979
|
|
|
$nodePath = $acctNode->_properties['id']; |
980
|
|
|
|
981
|
|
|
foreach($mailboxes as $k => $mbox) { |
982
|
|
|
$acctNode->add_node($this->buildTreeNode($k, $k, $mbox, $personalAccount->id, |
983
|
|
|
$nodePath, false, $personalAccount)); |
984
|
|
|
} |
985
|
|
|
|
986
|
|
|
$rootNode->add_node($acctNode); |
987
|
|
|
} |
988
|
|
|
} |
989
|
|
|
} |
990
|
|
|
|
991
|
|
|
// GROUP INBOX NODES |
992
|
|
|
$beans = $ie->retrieveAllByGroupId($current_user->id, false); |
993
|
|
|
foreach($beans as $k => $groupAccount) { |
994
|
|
|
if(in_array($groupAccount->id, $showFolders)) { |
995
|
|
|
// check for cache value |
996
|
|
|
$cacheRoot = sugar_cached("modules/Emails/{$groupAccount->id}"); |
997
|
|
|
$this->preflightEmailCache($cacheRoot); |
998
|
|
|
//$groupAccount->connectMailserver(); |
999
|
|
|
|
1000
|
|
|
if($this->validCacheFileExists($groupAccount->id, 'folders', "folders.php")) { |
1001
|
|
|
$mailboxes = $this->getMailBoxesFromCacheValue($groupAccount); |
1002
|
|
|
} else { |
1003
|
|
|
$mailboxes = $groupAccount->getMailBoxesForGroupAccount(); |
1004
|
|
|
} |
1005
|
|
|
|
1006
|
|
|
$acctNode = new ExtNode($groupAccount->name, "group.{$groupAccount->name}"); |
1007
|
|
|
$acctNode->dynamicloadfunction = ''; |
1008
|
|
|
$acctNode->expanded = false; |
1009
|
|
|
$acctNode->set_property('isGroup', 'true'); |
1010
|
|
|
$acctNode->set_property('ieId', $groupAccount->id); |
1011
|
|
|
$acctNode->set_property('protocol', $groupAccount->protocol); |
1012
|
|
|
|
1013
|
|
|
if(array_key_exists('Home::'.$groupAccount->name, $this->folderStates)) { |
1014
|
|
|
if($this->folderStates['Home::'.$groupAccount->name] == 'open') { |
1015
|
|
|
$acctNode->expanded = true; |
1016
|
|
|
} |
1017
|
|
|
} |
1018
|
|
|
$acctNode->dynamic_load = true; |
1019
|
|
|
$nodePath = $rootNode->_properties['id']."::".$acctNode->_properties['id']; |
1020
|
|
|
|
1021
|
|
|
foreach($mailboxes as $k => $mbox) { |
1022
|
|
|
$acctNode->add_node($this->buildTreeNode($k, $k, $mbox, $groupAccount->id, |
1023
|
|
|
$nodePath, true, $groupAccount)); |
1024
|
|
|
} |
1025
|
|
|
|
1026
|
|
|
$rootNode->add_node($acctNode); |
1027
|
|
|
} |
1028
|
|
|
} |
1029
|
|
|
|
1030
|
|
|
// SugarFolder nodes |
1031
|
|
|
/* SugarFolders are built at onload when the UI renders */ |
1032
|
|
|
|
1033
|
|
|
$tree->add_node($rootNode); |
1034
|
|
|
return $tree; |
1035
|
|
|
} |
1036
|
|
|
|
1037
|
|
|
function getMailBoxesFromCacheValue($mailAccount) { |
1038
|
|
|
$foldersCache = $this->getCacheValue($mailAccount->id, 'folders', "folders.php", 'foldersCache'); |
1039
|
|
|
$mailboxes = $foldersCache['mailboxes']; |
1040
|
|
|
$mailboxesArray = $mailAccount->generateFlatArrayFromMultiDimArray($mailboxes, $mailAccount->retrieveDelimiter()); |
1041
|
|
|
$mailAccount->saveMailBoxFolders($mailboxesArray); |
1042
|
|
|
$this->deleteEmailCacheForFolders($cacheRoot); |
1043
|
|
|
return $mailboxes; |
1044
|
|
|
} // fn |
1045
|
|
|
|
1046
|
|
|
/** |
1047
|
|
|
* Builds up a TreeView Node object |
1048
|
|
|
* @param mixed |
1049
|
|
|
* @param mixed |
1050
|
|
|
* @param string |
1051
|
|
|
* @param string ID of InboundEmail instance |
1052
|
|
|
* @param string nodePath Serialized path from root node to current node |
1053
|
|
|
* @param bool isGroup |
1054
|
|
|
* @param bool forceRefresh |
1055
|
|
|
* @return mixed |
1056
|
|
|
*/ |
1057
|
|
|
function buildTreeNode($key, $label, $mbox, $ieId, $nodePath, $isGroup, $ie) { |
1058
|
|
|
global $sugar_config; |
1059
|
|
|
|
1060
|
|
|
// get unread counts |
1061
|
|
|
$exMbox = explode("::", $nodePath); |
1062
|
|
|
$unseen = 0; |
1063
|
|
|
$GLOBALS['log']->debug("$key --- $nodePath::$label"); |
1064
|
|
|
|
1065
|
|
|
if(count($exMbox) >= 2) { |
1066
|
|
|
$mailbox = ""; |
1067
|
|
|
for($i=2; $i<count($exMbox); $i++) { |
|
|
|
|
1068
|
|
|
if($mailbox != "") { |
1069
|
|
|
$mailbox .= "."; |
1070
|
|
|
} |
1071
|
|
|
$mailbox .= "{$exMbox[$i]}"; |
1072
|
|
|
} |
1073
|
|
|
|
1074
|
|
|
$mailbox = substr($key, strpos($key, '.')); |
1075
|
|
|
|
1076
|
|
|
$unseen = $this->getUnreadCount($ie, $mailbox); |
1077
|
|
|
|
1078
|
|
|
if($unseen > 0) { |
|
|
|
|
1079
|
|
|
//$label = " <span id='span{$ie->id}{$ie->mailbox}' style='font-weight:bold'>{$label} (<span id='span{$ie->id}{$ie->mailbox}nums'>{$unseen}</span>)</span>"; |
1080
|
|
|
} |
1081
|
|
|
} |
1082
|
|
|
|
1083
|
|
|
$nodePath = $nodePath."::".$label; |
1084
|
|
|
$node = new ExtNode($nodePath, $label); |
1085
|
|
|
$node->dynamicloadfunction = ''; |
1086
|
|
|
$node->expanded = false; |
1087
|
|
|
$node->set_property('labelStyle', "remoteFolder"); |
1088
|
|
|
|
1089
|
|
|
|
1090
|
|
|
if(array_key_exists($nodePath, $this->folderStates)) { |
1091
|
|
|
if($this->folderStates[$nodePath] == 'open') { |
1092
|
|
|
$node->expanded = true; |
1093
|
|
|
} |
1094
|
|
|
} |
1095
|
|
|
|
1096
|
|
|
$group = ($isGroup) ? 'true' : 'false'; |
1097
|
|
|
$node->dynamic_load = true; |
1098
|
|
|
//$node->set_property('href', " SUGAR.email2.listView.populateListFrame(YAHOO.namespace('frameFolders').selectednode, '{$ieId}', 'false');"); |
1099
|
|
|
$node->set_property('isGroup', $group); |
1100
|
|
|
$node->set_property('isDynamic', 'false'); |
1101
|
|
|
$node->set_property('ieId', $ieId); |
1102
|
|
|
$node->set_property('mbox', $key); |
1103
|
|
|
$node->set_property('unseen', $unseen); |
1104
|
|
|
$node->set_property('cls', 'ieFolder'); |
1105
|
|
|
|
1106
|
|
|
if(is_array($mbox)) { |
1107
|
|
|
foreach($mbox as $k => $v) { |
1108
|
|
|
$node->add_node($this->buildTreeNode("$key.$k", $k, $v, $ieId, $nodePath, $isGroup, $ie)); |
1109
|
|
|
} |
1110
|
|
|
} |
1111
|
|
|
|
1112
|
|
|
return $node; |
1113
|
|
|
} |
1114
|
|
|
|
1115
|
|
|
/** |
1116
|
|
|
* Totals the unread emails |
1117
|
|
|
*/ |
1118
|
|
|
function getUnreadCount(&$ie, $mailbox) { |
1119
|
|
|
global $sugar_config; |
1120
|
|
|
$unseen = 0; |
1121
|
|
|
|
1122
|
|
|
// use cache |
1123
|
|
|
return $ie->getCacheUnreadCount($mailbox); |
1124
|
|
|
} |
1125
|
|
|
|
1126
|
|
|
/////////////////////////////////////////////////////////////////////////// |
1127
|
|
|
//// DISPLAY CODE |
1128
|
|
|
/** |
1129
|
|
|
* Used exclusively by draft code. Returns Notes and Documents as attachments. |
1130
|
|
|
* @param array $ret |
1131
|
|
|
* @return array |
1132
|
|
|
*/ |
1133
|
|
|
function getDraftAttachments($ret) { |
1134
|
|
|
global $db; |
1135
|
|
|
|
1136
|
|
|
// $ret['uid'] is the draft Email object's GUID |
1137
|
|
|
$ret['attachments'] = array(); |
1138
|
|
|
|
1139
|
|
|
$q = "SELECT id, filename FROM notes WHERE parent_id = '{$ret['uid']}' AND deleted = 0"; |
1140
|
|
|
$r = $db->query($q); |
1141
|
|
|
|
1142
|
|
|
while($a = $db->fetchByAssoc($r)) { |
1143
|
|
|
$ret['attachments'][$a['id']] = array( |
1144
|
|
|
'id' => $a['id'], |
1145
|
|
|
'filename' => $a['filename'], |
1146
|
|
|
); |
1147
|
|
|
} |
1148
|
|
|
|
1149
|
|
|
return $ret; |
1150
|
|
|
} |
1151
|
|
|
|
1152
|
|
|
function createCopyOfInboundAttachment($ie, $ret, $uid) { |
1153
|
|
|
global $sugar_config; |
1154
|
|
|
if ($ie->isPop3Protocol()) { |
1155
|
|
|
// get the UIDL from database; |
1156
|
|
|
$cachedUIDL = md5($uid); |
1157
|
|
|
$cache = sugar_cached("modules/Emails/{$ie->id}/messages/{$ie->mailbox}{$cachedUIDL}.php"); |
1158
|
|
|
} else { |
1159
|
|
|
$cache = sugar_cached("modules/Emails/{$ie->id}/messages/{$ie->mailbox}{$uid}.php"); |
1160
|
|
|
} |
1161
|
|
|
if(file_exists($cache)) { |
1162
|
|
|
include($cache); // profides $cacheFile |
1163
|
|
|
$metaOut = unserialize($cacheFile['out']); |
1164
|
|
|
$meta = $metaOut['meta']['email']; |
1165
|
|
|
if (isset($meta['attachments'])) { |
1166
|
|
|
$attachmentHtmlData = $meta['attachments']; |
1167
|
|
|
$actualAttachmentInfo = array(); |
1168
|
|
|
$this->parseAttachmentInfo($actualAttachmentInfo, $attachmentHtmlData); |
1169
|
|
|
if (sizeof($actualAttachmentInfo) > 0) { |
1170
|
|
|
foreach($actualAttachmentInfo as $key => $value) { |
1171
|
|
|
$info_vars = array(); |
1172
|
|
|
parse_str($value, $info_vars); |
1173
|
|
|
$fileName = $info_vars['tempName']; |
1174
|
|
|
$attachmentid = $info_vars['id']; |
1175
|
|
|
$guid = create_guid(); |
1176
|
|
|
$destination = clean_path("{$this->userCacheDir}/{$guid}"); |
1177
|
|
|
|
1178
|
|
|
$attachmentFilePath = sugar_cached("modules/Emails/{$ie->id}/attachments/{$attachmentid}"); |
1179
|
|
|
copy($attachmentFilePath, $destination); |
1180
|
|
|
$ret['attachments'][$guid] = array(); |
1181
|
|
|
$ret['attachments'][$guid]['id'] = $guid . $fileName; |
1182
|
|
|
$ret['attachments'][$guid]['filename'] = $fileName; |
1183
|
|
|
} // for |
1184
|
|
|
} // if |
1185
|
|
|
} // if |
1186
|
|
|
|
1187
|
|
|
} // if |
1188
|
|
|
return $ret; |
1189
|
|
|
|
1190
|
|
|
} // fn |
1191
|
|
|
|
1192
|
|
|
function parseAttachmentInfo(&$actualAttachmentInfo, $attachmentHtmlData) { |
1193
|
|
|
$downLoadPHP = strpos($attachmentHtmlData, "index.php?entryPoint=download&"); |
1194
|
|
|
while ($downLoadPHP) { |
1195
|
|
|
$attachmentHtmlData = substr($attachmentHtmlData, $downLoadPHP+30); |
1196
|
|
|
$final = strpos($attachmentHtmlData, "\">"); |
1197
|
|
|
$actualAttachmentInfo[] = substr($attachmentHtmlData, 0, $final); |
1198
|
|
|
$attachmentHtmlData = substr($attachmentHtmlData, $final); |
1199
|
|
|
$downLoadPHP = strpos($attachmentHtmlData, "index.php?entryPoint=download&"); |
1200
|
|
|
} // while |
1201
|
|
|
} |
1202
|
|
|
/** |
1203
|
|
|
* Renders the QuickCreate form from Smarty and returns HTML |
1204
|
|
|
* @param array $vars request variable global |
1205
|
|
|
* @param object $email Fetched email object |
1206
|
|
|
* @param bool $addToAddressBook |
|
|
|
|
1207
|
|
|
* @return array |
1208
|
|
|
*/ |
1209
|
|
|
function getQuickCreateForm($vars, $email, $addToAddressBookButton=false) { |
1210
|
|
|
require_once("include/EditView/EditView2.php"); |
1211
|
|
|
global $app_strings; |
1212
|
|
|
global $mod_strings; |
1213
|
|
|
global $current_user; |
1214
|
|
|
global $beanList; |
1215
|
|
|
global $beanFiles; |
1216
|
|
|
global $current_language; |
1217
|
|
|
|
1218
|
|
|
//Setup the current module languge |
1219
|
|
|
$mod_strings = return_module_language($current_language, $_REQUEST['qc_module']); |
1220
|
|
|
|
1221
|
|
|
$bean = $beanList[$_REQUEST['qc_module']]; |
1222
|
|
|
$class = $beanFiles[$bean]; |
1223
|
|
|
require_once($class); |
1224
|
|
|
|
1225
|
|
|
$focus = new $bean(); |
1226
|
|
|
|
1227
|
|
|
$people = array( |
1228
|
|
|
'Contact' |
1229
|
|
|
,'Lead' |
1230
|
|
|
); |
1231
|
|
|
$emailAddress = array(); |
1232
|
|
|
|
1233
|
|
|
// people |
1234
|
|
|
if(in_array($bean, $people)) { |
1235
|
|
|
// lead specific |
1236
|
|
|
$focus->lead_source = 'Email'; |
1237
|
|
|
$focus->lead_source_description = trim($email->name); |
1238
|
|
|
|
1239
|
|
|
$from = (isset($email->from_name) && !empty($email->from_name)) ? $email->from_name : $email->from_addr; |
1240
|
|
|
|
1241
|
|
|
if(isset($_REQUEST['sugarEmail']) && !empty($_REQUEST['sugarEmail'])) |
1242
|
|
|
{ |
1243
|
|
|
if($email->status == "sent") |
1244
|
|
|
{ |
1245
|
|
|
$from = (isset($email->to_addrs_names) && !empty($email->to_addrs_names)) ? $email->to_addrs_names : $email->to_addrs; |
1246
|
|
|
}else{ |
1247
|
|
|
$from = (isset($email->from_name) && !empty($email->from_name)) ? $email->from_name : $email->from_addr_name; |
1248
|
|
|
} |
1249
|
|
|
} |
1250
|
|
|
|
1251
|
|
|
$name = explode(" ", trim($from)); |
1252
|
|
|
|
1253
|
|
|
$address = trim(array_pop($name)); |
1254
|
|
|
$address = str_replace(array("<",">","<",">"), "", $address); |
1255
|
|
|
|
1256
|
|
|
$emailAddress[] = array( |
1257
|
|
|
'email_address' => $address, |
1258
|
|
|
'primary_address' => 1, |
1259
|
|
|
'invalid_email' => 0, |
1260
|
|
|
'opt_out' => 0, |
1261
|
|
|
'reply_to_address' => 1 |
1262
|
|
|
); |
1263
|
|
|
|
1264
|
|
|
$focus->email1 = $address; |
1265
|
|
|
|
1266
|
|
|
if(!empty($name)) { |
1267
|
|
|
$focus->last_name = trim(array_pop($name)); |
1268
|
|
|
|
1269
|
|
|
foreach($name as $first) { |
1270
|
|
|
if(!empty($focus->first_name)) { |
1271
|
|
|
$focus->first_name .= " "; |
1272
|
|
|
} |
1273
|
|
|
$focus->first_name .= trim($first); |
1274
|
|
|
} |
1275
|
|
|
} |
1276
|
|
|
} else { |
1277
|
|
|
// bugs, cases, tasks |
1278
|
|
|
$focus->name = trim($email->name); |
1279
|
|
|
} |
1280
|
|
|
|
1281
|
|
|
$focus->description = trim(strip_tags($email->description)); |
1282
|
|
|
$focus->assigned_user_id = $current_user->id; |
1283
|
|
|
|
1284
|
|
|
|
1285
|
|
|
$EditView = new EditView(); |
|
|
|
|
1286
|
|
|
$EditView->ss = new Sugar_Smarty(); |
1287
|
|
|
//MFH BUG#20283 - checks for custom quickcreate fields |
1288
|
|
|
$EditView->setup($_REQUEST['qc_module'], $focus, 'custom/modules/'.$focus->module_dir.'/metadata/editviewdefs.php', 'include/EditView/EditView.tpl'); |
1289
|
|
|
$EditView->process(); |
1290
|
|
|
$EditView->render(); |
|
|
|
|
1291
|
|
|
|
1292
|
|
|
$EditView->defs['templateMeta']['form']['buttons'] = array( |
1293
|
|
|
'email2save' => array( |
1294
|
|
|
'id' => 'e2AjaxSave', |
1295
|
|
|
'customCode' => '<input type="button" class="button" value=" '.$app_strings['LBL_SAVE_BUTTON_LABEL'] |
1296
|
|
|
. ' " onclick="SUGAR.email2.detailView.saveQuickCreate(false);" />' |
1297
|
|
|
), |
1298
|
|
|
'email2saveandreply' => array( |
1299
|
|
|
'id' => 'e2SaveAndReply', |
1300
|
|
|
'customCode' => '<input type="button" class="button" value=" '.$app_strings['LBL_EMAIL_SAVE_AND_REPLY'] |
1301
|
|
|
. ' " onclick="SUGAR.email2.detailView.saveQuickCreate(\'reply\');" />' |
1302
|
|
|
), |
1303
|
|
|
'email2cancel' => array( |
1304
|
|
|
'id' => 'e2cancel', |
1305
|
|
|
'customCode' => '<input type="button" class="button" value=" '.$app_strings['LBL_EMAIL_CANCEL'] |
1306
|
|
|
. ' " onclick="SUGAR.email2.detailView.quickCreateDialog.hide();" />' |
1307
|
|
|
) |
1308
|
|
|
); |
1309
|
|
|
|
1310
|
|
|
|
1311
|
|
|
if($addToAddressBookButton) { |
1312
|
|
|
$EditView->defs['templateMeta']['form']['buttons']['email2saveAddToAddressBook'] = array( |
1313
|
|
|
'id' => 'e2addToAddressBook', |
1314
|
|
|
'customCode' => '<input type="button" class="button" value=" '.$app_strings['LBL_EMAIL_ADDRESS_BOOK_SAVE_AND_ADD'] |
1315
|
|
|
. ' " onclick="SUGAR.email2.detailView.saveQuickCreate(true);" />' |
1316
|
|
|
); |
1317
|
|
|
} |
1318
|
|
|
|
1319
|
|
|
//Get the module language for javascript |
1320
|
|
|
if(!is_file(sugar_cached('jsLanguage/') . $_REQUEST['qc_module'] . '/' . $GLOBALS['current_language'] . '.js')) { |
1321
|
|
|
require_once('include/language/jsLanguage.php'); |
1322
|
|
|
jsLanguage::createModuleStringsCache($_REQUEST['qc_module'], $GLOBALS['current_language']); |
1323
|
|
|
} |
1324
|
|
|
$jsLanguage = getVersionedScript("cache/jsLanguage/{$_REQUEST['qc_module']}/{$GLOBALS['current_language']}.js", $GLOBALS['sugar_config']['js_lang_version']); |
1325
|
|
|
|
1326
|
|
|
|
1327
|
|
|
$EditView->view = 'EmailQCView'; |
1328
|
|
|
$EditView->defs['templateMeta']['form']['headerTpl'] = 'include/EditView/header.tpl'; |
1329
|
|
|
$EditView->defs['templateMeta']['form']['footerTpl'] = 'include/EditView/footer.tpl'; |
1330
|
|
|
$meta = array(); |
1331
|
|
|
$meta['html'] = $jsLanguage . $EditView->display(false, true); |
|
|
|
|
1332
|
|
|
$meta['html'] = str_replace("src='".getVersionedPath('include/SugarEmailAddress/SugarEmailAddress.js')."'", '', $meta['html']); |
1333
|
|
|
$meta['emailAddress'] = $emailAddress; |
1334
|
|
|
|
1335
|
|
|
$mod_strings = return_module_language($current_language, 'Emails'); |
1336
|
|
|
|
1337
|
|
|
return $meta; |
1338
|
|
|
} |
1339
|
|
|
|
1340
|
|
|
/** |
1341
|
|
|
* Renders the Import form from Smarty and returns HTML |
1342
|
|
|
* @param array $vars request variable global |
1343
|
|
|
* @param object $email Fetched email object |
1344
|
|
|
* @param bool $addToAddressBook |
|
|
|
|
1345
|
|
|
* @return array |
1346
|
|
|
*/ |
1347
|
|
|
function getImportForm($vars, $email, $formName = 'ImportEditView') { |
1348
|
|
|
require_once("include/EditView/EditView2.php"); |
1349
|
|
|
require_once("include/TemplateHandler/TemplateHandler.php"); |
1350
|
|
|
require_once('include/QuickSearchDefaults.php'); |
1351
|
|
|
$qsd = QuickSearchDefaults::getQuickSearchDefaults(); |
1352
|
|
|
$qsd->setFormName($formName); |
1353
|
|
|
|
1354
|
|
|
global $app_strings; |
1355
|
|
|
global $current_user; |
1356
|
|
|
global $app_list_strings; |
1357
|
|
|
$sqs_objects = array( |
1358
|
|
|
"{$formName}_parent_name" => $qsd->getQSParent(), |
1359
|
|
|
); |
1360
|
|
|
$smarty = new Sugar_Smarty(); |
1361
|
|
|
$smarty->assign("APP",$app_strings); |
1362
|
|
|
$smarty->assign('formName',$formName); |
1363
|
|
|
$showAssignTo = false; |
1364
|
|
|
if (!isset($vars['showAssignTo']) || $vars['showAssignTo'] == true) { |
1365
|
|
|
$showAssignTo = true; |
1366
|
|
|
} // if |
1367
|
|
|
if ($showAssignTo) { |
1368
|
|
|
if(empty($email->assigned_user_id) && empty($email->id)) |
1369
|
|
|
$email->assigned_user_id = $current_user->id; |
1370
|
|
|
if(empty($email->assigned_name) && empty($email->id)) |
1371
|
|
|
$email->assigned_user_name = $current_user->user_name; |
1372
|
|
|
$sqs_objects["{$formName}_assigned_user_name"] = $qsd->getQSUser(); |
1373
|
|
|
} |
1374
|
|
|
$smarty->assign("showAssignedTo",$showAssignTo); |
1375
|
|
|
|
1376
|
|
|
$showDelete = false; |
1377
|
|
|
if (!isset($vars['showDelete']) || $vars['showDelete'] == true) { |
1378
|
|
|
$showDelete = true; |
1379
|
|
|
} |
1380
|
|
|
$smarty->assign("showDelete",$showDelete); |
1381
|
|
|
|
1382
|
|
|
$smarty->assign("userId",$email->assigned_user_id); |
1383
|
|
|
$smarty->assign("userName",$email->assigned_user_name); |
1384
|
|
|
$parent_types = $app_list_strings['record_type_display']; |
1385
|
|
|
$smarty->assign('parentOptions', get_select_options_with_id($parent_types, $email->parent_type)); |
1386
|
|
|
|
1387
|
|
|
$quicksearch_js = '<script type="text/javascript" language="javascript">sqs_objects = ' . json_encode($sqs_objects) . '</script>'; |
1388
|
|
|
$smarty->assign('SQS', $quicksearch_js); |
1389
|
|
|
|
1390
|
|
|
$meta = array(); |
1391
|
|
|
$meta['html'] = $smarty->fetch("modules/Emails/templates/importRelate.tpl"); |
1392
|
|
|
return $meta; |
1393
|
|
|
} |
1394
|
|
|
|
1395
|
|
|
/** |
1396
|
|
|
* This function returns the detail view for email in new 2.0 interface |
1397
|
|
|
* |
1398
|
|
|
*/ |
1399
|
|
|
function getDetailViewForEmail2($emailId) { |
1400
|
|
|
|
1401
|
|
|
require_once('include/DetailView/DetailView.php'); |
1402
|
|
|
global $app_strings, $app_list_strings; |
1403
|
|
|
global $mod_strings; |
1404
|
|
|
|
1405
|
|
|
$smarty = new Sugar_Smarty(); |
1406
|
|
|
|
1407
|
|
|
// SETTING DEFAULTS |
1408
|
|
|
$focus = new Email(); |
1409
|
|
|
$focus->retrieve($emailId); |
1410
|
|
|
$detailView->ss = new Sugar_Smarty(); |
|
|
|
|
1411
|
|
|
$detailView = new DetailView(); |
1412
|
|
|
$title = ""; |
1413
|
|
|
$offset = 0; |
1414
|
|
|
if($focus->type == 'out') { |
1415
|
|
|
$title = getClassicModuleTitle('Emails', array($mod_strings['LBL_SENT_MODULE_NAME'],$focus->name), true); |
1416
|
|
|
} elseif ($focus->type == 'draft') { |
1417
|
|
|
$title = getClassicModuleTitle('Emails', array($mod_strings['LBL_LIST_FORM_DRAFTS_TITLE'],$focus->name), true); |
1418
|
|
|
} elseif($focus->type == 'inbound') { |
1419
|
|
|
$title = getClassicModuleTitle('Emails', array($mod_strings['LBL_INBOUND_TITLE'],$focus->name), true); |
1420
|
|
|
} |
1421
|
|
|
$smarty->assign("emailTitle", $title); |
1422
|
|
|
|
1423
|
|
|
// DEFAULT TO TEXT IF NO HTML CONTENT: |
1424
|
|
|
$html = trim(from_html($focus->description_html)); |
1425
|
|
|
if(empty($html)) { |
1426
|
|
|
$smarty->assign('SHOW_PLAINTEXT', 'true'); |
1427
|
|
|
} else { |
1428
|
|
|
$smarty->assign('SHOW_PLAINTEXT', 'false'); |
1429
|
|
|
} |
1430
|
|
|
|
1431
|
|
|
//if not empty or set to test (from test campaigns) |
1432
|
|
|
if (!empty($focus->parent_type) && $focus->parent_type !='test') { |
1433
|
|
|
$smarty->assign('PARENT_MODULE', $focus->parent_type); |
1434
|
|
|
$smarty->assign('PARENT_TYPE', $app_list_strings['record_type_display'][$focus->parent_type] . ":"); |
1435
|
|
|
} |
1436
|
|
|
|
1437
|
|
|
global $gridline; |
1438
|
|
|
$smarty->assign('MOD', $mod_strings); |
1439
|
|
|
$smarty->assign('APP', $app_strings); |
1440
|
|
|
$smarty->assign('GRIDLINE', $gridline); |
1441
|
|
|
$smarty->assign('PRINT_URL', 'index.php?'.$GLOBALS['request_string']); |
1442
|
|
|
$smarty->assign('ID', $focus->id); |
1443
|
|
|
$smarty->assign('TYPE', $focus->type); |
1444
|
|
|
$smarty->assign('PARENT_NAME', $focus->parent_name); |
1445
|
|
|
$smarty->assign('PARENT_ID', $focus->parent_id); |
1446
|
|
|
$smarty->assign('NAME', $focus->name); |
1447
|
|
|
$smarty->assign('ASSIGNED_TO', $focus->assigned_user_name); |
1448
|
|
|
$smarty->assign('DATE_MODIFIED', $focus->date_modified); |
1449
|
|
|
$smarty->assign('DATE_ENTERED', $focus->date_entered); |
1450
|
|
|
$smarty->assign('DATE_START', $focus->date_start); |
1451
|
|
|
$smarty->assign('TIME_START', $focus->time_start); |
1452
|
|
|
$smarty->assign('FROM', $focus->from_addr); |
1453
|
|
|
$smarty->assign('TO', nl2br($focus->to_addrs)); |
1454
|
|
|
$smarty->assign('CC', nl2br($focus->cc_addrs)); |
1455
|
|
|
$smarty->assign('BCC', nl2br($focus->bcc_addrs)); |
1456
|
|
|
$smarty->assign('CREATED_BY', $focus->created_by_name); |
1457
|
|
|
$smarty->assign('MODIFIED_BY', $focus->modified_by_name); |
1458
|
|
|
$smarty->assign('DATE_SENT', $focus->date_entered); |
1459
|
|
|
$smarty->assign('EMAIL_NAME', 'RE: '.$focus->name); |
1460
|
|
|
$smarty->assign("TAG", $focus->listviewACLHelper()); |
1461
|
|
|
$smarty->assign("SUGAR_VERSION", $GLOBALS['sugar_version']); |
1462
|
|
|
$smarty->assign("JS_CUSTOM_VERSION", $GLOBALS['sugar_config']['js_custom_version']); |
1463
|
|
|
if(!empty($focus->reply_to_email)) { |
1464
|
|
|
$replyTo = " |
1465
|
|
|
<tr> |
1466
|
|
|
<td class=\"tabDetailViewDL\"><slot>".$mod_strings['LBL_REPLY_TO_NAME']."</slot></td> |
1467
|
|
|
<td colspan=3 class=\"tabDetailViewDF\"><slot>".$focus->reply_to_addr."</slot></td> |
1468
|
|
|
</tr>"; |
1469
|
|
|
$smarty->assign("REPLY_TO", $replyTo); |
1470
|
|
|
} |
1471
|
|
|
/////////////////////////////////////////////////////////////////////////////// |
1472
|
|
|
//// JAVASCRIPT VARS |
1473
|
|
|
$jsVars = ''; |
1474
|
|
|
$jsVars .= "var showRaw = '{$mod_strings['LBL_BUTTON_RAW_LABEL']}';"; |
1475
|
|
|
$jsVars .= "var hideRaw = '{$mod_strings['LBL_BUTTON_RAW_LABEL_HIDE']}';"; |
1476
|
|
|
$smarty->assign("JS_VARS", $jsVars); |
1477
|
|
|
/////////////////////////////////////////////////////////////////////////////// |
1478
|
|
|
//// NOTES (attachements, etc.) |
1479
|
|
|
/////////////////////////////////////////////////////////////////////////////// |
1480
|
|
|
|
1481
|
|
|
$note = new Note(); |
1482
|
|
|
$where = "notes.parent_id='{$focus->id}'"; |
1483
|
|
|
//take in account if this is from campaign and the template id is stored in the macros. |
1484
|
|
|
|
1485
|
|
|
if(isset($macro_values) && isset($macro_values['email_template_id'])){ |
|
|
|
|
1486
|
|
|
$where = "notes.parent_id='{$macro_values['email_template_id']}'"; |
1487
|
|
|
} |
1488
|
|
|
$notes_list = $note->get_full_list("notes.name", $where, true); |
1489
|
|
|
|
1490
|
|
|
if(! isset($notes_list)) { |
1491
|
|
|
$notes_list = array(); |
1492
|
|
|
} |
1493
|
|
|
|
1494
|
|
|
$attachments = ''; |
1495
|
|
|
for($i=0; $i<count($notes_list); $i++) { |
|
|
|
|
1496
|
|
|
$the_note = $notes_list[$i]; |
1497
|
|
|
$attachments .= "<a href=\"index.php?entryPoint=download&id={$the_note->id}&type=Notes\">".$the_note->name."</a><br />"; |
1498
|
|
|
$focus->cid2Link($the_note->id, $the_note->file_mime_type); |
1499
|
|
|
} |
1500
|
|
|
$smarty->assign('DESCRIPTION', nl2br($focus->description)); |
1501
|
|
|
$smarty->assign('DESCRIPTION_HTML', from_html($focus->description_html)); |
1502
|
|
|
$smarty->assign("ATTACHMENTS", $attachments); |
1503
|
|
|
/////////////////////////////////////////////////////////////////////////////// |
1504
|
|
|
//// SUBPANELS |
1505
|
|
|
/////////////////////////////////////////////////////////////////////////////// |
1506
|
|
|
$show_subpanels = true; |
1507
|
|
|
if ($show_subpanels) { |
1508
|
|
|
require_once('include/SubPanel/SubPanelTiles.php'); |
1509
|
|
|
$subpanel = new SubPanelTiles($focus, 'Emails'); |
1510
|
|
|
$smarty->assign("SUBPANEL", $subpanel->display()); |
1511
|
|
|
} |
1512
|
|
|
$meta['html'] = $smarty->fetch("modules/Emails/templates/emailDetailView.tpl"); |
1513
|
|
|
return $meta; |
1514
|
|
|
|
1515
|
|
|
} // fn |
1516
|
|
|
|
1517
|
|
|
/** |
1518
|
|
|
* Sets the "read" flag in the overview cache |
1519
|
|
|
*/ |
1520
|
|
|
function setReadFlag($ieId, $mbox, $uid) { |
1521
|
|
|
$this->markEmails('read', $ieId, $mbox, $uid); |
1522
|
|
|
} |
1523
|
|
|
|
1524
|
|
|
/** |
1525
|
|
|
* Marks emails with the passed flag type. This will be applied to local |
1526
|
|
|
* cache files as well as remote emails. |
1527
|
|
|
* @param string $type Flag type |
1528
|
|
|
* @param string $ieId |
1529
|
|
|
* @param string $folder IMAP folder structure or SugarFolder GUID |
1530
|
|
|
* @param string $uids Comma sep list of UIDs or GUIDs |
1531
|
|
|
*/ |
1532
|
|
|
function markEmails($type, $ieId, $folder, $uids) { |
1533
|
|
|
|
1534
|
|
|
global $app_strings; |
1535
|
|
|
$uids = $this->_cleanUIDList($uids); |
1536
|
|
|
$exUids = explode($app_strings['LBL_EMAIL_DELIMITER'], $uids); |
1537
|
|
|
|
1538
|
|
|
if(strpos($folder, 'sugar::') !== false) { |
1539
|
|
|
// dealing with a sugar email object, uids are GUIDs |
1540
|
|
|
foreach($exUids as $id) { |
1541
|
|
|
$email = new Email(); |
1542
|
|
|
$email->retrieve($id); |
1543
|
|
|
|
1544
|
|
|
// BUG FIX BEGIN |
1545
|
|
|
// Bug 50973 - marking unread in group inbox removes message |
1546
|
|
|
if (empty($email->assigned_user_id)) |
1547
|
|
|
{ |
1548
|
|
|
$email->setFieldNullable('assigned_user_id'); |
1549
|
|
|
} |
1550
|
|
|
// BUG FIX END |
1551
|
|
|
|
1552
|
|
|
switch($type) { |
1553
|
|
|
case "unread": |
1554
|
|
|
$email->status = 'unread'; |
1555
|
|
|
$email->save(); |
1556
|
|
|
break; |
1557
|
|
|
|
1558
|
|
|
case "read": |
1559
|
|
|
$email->status = 'read'; |
1560
|
|
|
$email->save(); |
1561
|
|
|
break; |
1562
|
|
|
|
1563
|
|
|
case "deleted": |
1564
|
|
|
$email->delete(); |
1565
|
|
|
break; |
1566
|
|
|
|
1567
|
|
|
case "flagged": |
1568
|
|
|
$email->flagged = 1; |
1569
|
|
|
$email->save(); |
1570
|
|
|
break; |
1571
|
|
|
|
1572
|
|
|
case "unflagged": |
1573
|
|
|
$email->flagged = 0; |
1574
|
|
|
$email->save(); |
1575
|
|
|
break; |
1576
|
|
|
|
1577
|
|
|
} |
1578
|
|
|
|
1579
|
|
|
// BUG FIX BEGIN |
1580
|
|
|
// Bug 50973 - reset assigned_user_id field defs |
1581
|
|
|
if (empty($email->assigned_user_id)) |
1582
|
|
|
{ |
1583
|
|
|
$email->revertFieldNullable('assigned_user_id'); |
1584
|
|
|
} |
1585
|
|
|
// BUG FIX END |
1586
|
|
|
} |
1587
|
|
|
} else { |
1588
|
|
|
/* dealing with IMAP email, uids are IMAP uids */ |
1589
|
|
|
global $ie; // provided by EmailUIAjax.php |
1590
|
|
|
if(empty($ie)) { |
1591
|
|
|
|
1592
|
|
|
$ie = new InboundEmail(); |
1593
|
|
|
} |
1594
|
|
|
$ie->retrieve($ieId); |
1595
|
|
|
$ie->mailbox = $folder; |
1596
|
|
|
$ie->connectMailserver(); |
1597
|
|
|
// mark cache files |
1598
|
|
|
if($type == 'deleted') { |
1599
|
|
|
$ie->deleteMessageOnMailServer($uids); |
|
|
|
|
1600
|
|
|
$ie->deleteMessageFromCache($uids); |
1601
|
|
|
} else { |
1602
|
|
|
$overviews = $ie->getCacheValueForUIDs($ie->mailbox, $exUids); |
1603
|
|
|
$manipulated = array(); |
1604
|
|
|
|
1605
|
|
|
foreach($overviews['retArr'] as $k => $overview) { |
1606
|
|
|
if(in_array($overview->uid, $exUids)) { |
1607
|
|
|
switch($type) { |
1608
|
|
|
case "unread": |
1609
|
|
|
$overview->seen = 0; |
1610
|
|
|
break; |
1611
|
|
|
|
1612
|
|
|
case "read": |
1613
|
|
|
$overview->seen = 1; |
1614
|
|
|
break; |
1615
|
|
|
|
1616
|
|
|
case "flagged": |
1617
|
|
|
$overview->flagged = 1; |
1618
|
|
|
break; |
1619
|
|
|
|
1620
|
|
|
case "unflagged": |
1621
|
|
|
$overview->flagged = 0; |
1622
|
|
|
break; |
1623
|
|
|
} |
1624
|
|
|
$manipulated[] = $overview; |
1625
|
|
|
} |
1626
|
|
|
} |
1627
|
|
|
|
1628
|
|
|
if(!empty($manipulated)) { |
1629
|
|
|
$ie->setCacheValue($ie->mailbox, array(), $manipulated); |
1630
|
|
|
/* now mark emails on email server */ |
1631
|
|
|
$ie->markEmails(implode(",", explode($app_strings['LBL_EMAIL_DELIMITER'], $uids)), $type); |
1632
|
|
|
} |
1633
|
|
|
} // end not type == deleted |
1634
|
|
|
} |
1635
|
|
|
} |
1636
|
|
|
|
1637
|
|
|
function doAssignment($distributeMethod, $ieid, $folder, $uids, $users) { |
1638
|
|
|
global $app_strings; |
1639
|
|
|
$users = explode(",", $users); |
1640
|
|
|
$emailIds = explode($app_strings['LBL_EMAIL_DELIMITER'], $uids); |
1641
|
|
|
$out = ""; |
1642
|
|
|
if($folder != 'sugar::Emails') { |
1643
|
|
|
$emailIds = array(); |
1644
|
|
|
$uids = explode($app_strings['LBL_EMAIL_DELIMITER'], $uids); |
1645
|
|
|
$ie = new InboundEmail(); |
1646
|
|
|
$ie->retrieve($ieid); |
1647
|
|
|
$messageIndex = 1; |
1648
|
|
|
// dealing with an inbound email data so we need to import an email and then |
1649
|
|
|
foreach($uids as $uid) { |
1650
|
|
|
$ie->mailbox = $folder; |
1651
|
|
|
$ie->connectMailserver(); |
1652
|
|
|
$msgNo = $uid; |
1653
|
|
|
if (!$ie->isPop3Protocol()) { |
1654
|
|
|
$msgNo = imap_msgno($ie->conn, $uid); |
1655
|
|
|
} else { |
1656
|
|
|
$msgNo = $ie->getCorrectMessageNoForPop3($uid); |
1657
|
|
|
} |
1658
|
|
|
|
1659
|
|
|
if(!empty($msgNo)) { |
1660
|
|
|
if ($ie->importOneEmail($msgNo, $uid)) { |
1661
|
|
|
$emailIds[] = $ie->email->id; |
1662
|
|
|
$ie->deleteMessageOnMailServer($uid); |
1663
|
|
|
//$ie->retrieve($ieid); |
1664
|
|
|
//$ie->connectMailserver(); |
1665
|
|
|
$ie->mailbox = $folder; |
1666
|
|
|
$ie->deleteMessageFromCache(($uids[] = $uid)); |
1667
|
|
|
} else { |
1668
|
|
|
$out = $out . "Message No : " . $messageIndex . " failed. Reason : Message already imported \r\n"; |
1669
|
|
|
} |
1670
|
|
|
} |
1671
|
|
|
$messageIndex++; |
1672
|
|
|
} // for |
1673
|
|
|
} // if |
1674
|
|
|
|
1675
|
|
|
if (count($emailIds) > 0) { |
1676
|
|
|
$this->doDistributionWithMethod($users, $emailIds, $distributeMethod); |
1677
|
|
|
} // if |
1678
|
|
|
return $out; |
1679
|
|
|
} // fn |
1680
|
|
|
|
1681
|
|
|
/** |
1682
|
|
|
* get team id and team set id from request |
1683
|
|
|
* @return array |
1684
|
|
|
*/ |
1685
|
|
|
function getTeams() { |
1686
|
|
|
} |
1687
|
|
|
|
1688
|
|
|
function doDistributionWithMethod($users, $emailIds, $distributionMethod) { |
1689
|
|
|
// we have users and the items to distribute |
1690
|
|
|
if($distributionMethod == 'roundRobin') { |
1691
|
|
|
$this->distRoundRobin($users, $emailIds); |
1692
|
|
|
} elseif($distributionMethod == 'leastBusy') { |
1693
|
|
|
$this->distLeastBusy($users, $emailIds); |
1694
|
|
|
} elseif($distributionMethod == 'direct') { |
1695
|
|
|
if(count($users) > 1) { |
1696
|
|
|
// only 1 user allowed in direct assignment |
1697
|
|
|
$error = 1; |
1698
|
|
|
} else { |
1699
|
|
|
$user = $users[0]; |
1700
|
|
|
$this->distDirect($user, $emailIds); |
1701
|
|
|
} // else |
1702
|
|
|
} // elseif |
1703
|
|
|
|
1704
|
|
|
} // fn |
1705
|
|
|
|
1706
|
|
|
/** |
1707
|
|
|
* distributes emails to users on Round Robin basis |
1708
|
|
|
* @param $userIds array of users to dist to |
1709
|
|
|
* @param $mailIds array of email ids to push on those users |
1710
|
|
|
* @return boolean true on success |
1711
|
|
|
*/ |
1712
|
|
|
function distRoundRobin($userIds, $mailIds) { |
1713
|
|
|
// check if we have a 'lastRobin' |
1714
|
|
|
$lastRobin = $userIds[0]; |
1715
|
|
|
foreach($mailIds as $k => $mailId) { |
1716
|
|
|
$userIdsKeys = array_flip($userIds); // now keys are values |
1717
|
|
|
$thisRobinKey = $userIdsKeys[$lastRobin] + 1; |
1718
|
|
|
if(!empty($userIds[$thisRobinKey])) { |
1719
|
|
|
$thisRobin = $userIds[$thisRobinKey]; |
1720
|
|
|
$lastRobin = $userIds[$thisRobinKey]; |
1721
|
|
|
} else { |
1722
|
|
|
$thisRobin = $userIds[0]; |
1723
|
|
|
$lastRobin = $userIds[0]; |
1724
|
|
|
} |
1725
|
|
|
|
1726
|
|
|
$email = new Email(); |
1727
|
|
|
$email->retrieve($mailId); |
1728
|
|
|
$email->assigned_user_id = $thisRobin; |
1729
|
|
|
$email->status = 'unread'; |
1730
|
|
|
$email->save(); |
1731
|
|
|
} |
1732
|
|
|
|
1733
|
|
|
return true; |
1734
|
|
|
} |
1735
|
|
|
|
1736
|
|
|
/** |
1737
|
|
|
* distributes emails to users on Least Busy basis |
1738
|
|
|
* @param $userIds array of users to dist to |
1739
|
|
|
* @param $mailIds array of email ids to push on those users |
1740
|
|
|
* @return boolean true on success |
1741
|
|
|
*/ |
1742
|
|
|
function distLeastBusy($userIds, $mailIds) { |
1743
|
|
|
foreach($mailIds as $k => $mailId) { |
1744
|
|
|
$email = new Email(); |
1745
|
|
|
$email->retrieve($mailId); |
1746
|
|
|
foreach($userIds as $k => $id) { |
1747
|
|
|
$r = $this->db->query("SELECT count(*) AS c FROM emails WHERE assigned_user_id = '.$id.' AND status = 'unread'"); |
1748
|
|
|
$a = $this->db->fetchByAssoc($r); |
1749
|
|
|
$counts[$id] = $a['c']; |
1750
|
|
|
} |
1751
|
|
|
asort($counts); // lowest to highest |
1752
|
|
|
$countsKeys = array_flip($counts); // keys now the 'count of items' |
1753
|
|
|
$leastBusy = array_shift($countsKeys); // user id of lowest item count |
1754
|
|
|
$email->assigned_user_id = $leastBusy; |
1755
|
|
|
$email->status = 'unread'; |
1756
|
|
|
$email->save(); |
1757
|
|
|
} |
1758
|
|
|
return true; |
1759
|
|
|
} |
1760
|
|
|
|
1761
|
|
|
/** |
1762
|
|
|
* distributes emails to 1 user |
1763
|
|
|
* @param $user users to dist to |
1764
|
|
|
* @param $mailIds array of email ids to push |
1765
|
|
|
* @return boolean true on success |
1766
|
|
|
*/ |
1767
|
|
|
function distDirect($user, $mailIds) { |
1768
|
|
|
foreach($mailIds as $k => $mailId) { |
1769
|
|
|
$email = new Email(); |
1770
|
|
|
$email->retrieve($mailId); |
1771
|
|
|
$email->assigned_user_id = $user; |
1772
|
|
|
$email->status = 'unread'; |
1773
|
|
|
|
1774
|
|
|
$email->save(); |
1775
|
|
|
} |
1776
|
|
|
return true; |
1777
|
|
|
} |
1778
|
|
|
|
1779
|
|
|
function getAssignedEmailsCountForUsers($userIds) { |
1780
|
|
|
$counts = array(); |
1781
|
|
|
foreach($userIds as $id) { |
1782
|
|
|
$r = $this->db->query("SELECT count(*) AS c FROM emails WHERE assigned_user_id = '$id' AND status = 'unread'"); |
1783
|
|
|
$a = $this->db->fetchByAssoc($r); |
1784
|
|
|
$counts[$id] = $a['c']; |
1785
|
|
|
} // foreach |
1786
|
|
|
return $counts; |
1787
|
|
|
} // fn |
1788
|
|
|
|
1789
|
|
|
function getLastRobin($ie) { |
1790
|
|
|
$lastRobin = ""; |
1791
|
|
|
if($this->validCacheFileExists($ie->id, 'folders', "robin.cache.php")) { |
1792
|
|
|
$lastRobin = $this->getCacheValue($ie->id, 'folders', "robin.cache.php", 'robin'); |
1793
|
|
|
} // if |
1794
|
|
|
return $lastRobin; |
1795
|
|
|
} // fn |
1796
|
|
|
|
1797
|
|
|
function setLastRobin($ie, $lastRobin) { |
1798
|
|
|
global $sugar_config; |
1799
|
|
|
$cacheFolderPath = sugar_cached("modules/Emails/{$ie->id}/folders"); |
1800
|
|
|
if (!file_exists($cacheFolderPath)) { |
1801
|
|
|
mkdir_recursive($cacheFolderPath); |
1802
|
|
|
} |
1803
|
|
|
$this->writeCacheFile('robin', $lastRobin, $ie->id, 'folders', "robin.cache.php"); |
1804
|
|
|
} // fn |
1805
|
|
|
|
1806
|
|
|
/** |
1807
|
|
|
* returns the metadata defining a single email message for display. Uses cache file if it exists |
1808
|
|
|
* @return array |
1809
|
|
|
*/ |
1810
|
|
|
function getSingleMessage($ie) { |
1811
|
|
|
|
1812
|
|
|
global $timedate; |
1813
|
|
|
global $app_strings,$mod_strings; |
1814
|
|
|
$ie->retrieve($_REQUEST['ieId']); |
1815
|
|
|
$noCache = true; |
1816
|
|
|
|
1817
|
|
|
$ie->mailbox = $_REQUEST['mbox']; |
1818
|
|
|
$filename = $_REQUEST['mbox'].$_REQUEST['uid'].".php"; |
1819
|
|
|
$md5uidl = ""; |
1820
|
|
|
if ($ie->isPop3Protocol()) { |
1821
|
|
|
$md5uidl = md5($_REQUEST['uid']); |
1822
|
|
|
$filename = $_REQUEST['mbox'].$md5uidl.".php"; |
1823
|
|
|
} // if |
1824
|
|
|
|
1825
|
|
|
if(isset($filename) && strpos($filename, "..") !== false){ |
1826
|
|
|
die("Directory navigation attack denied."); |
1827
|
|
|
} |
1828
|
|
|
|
1829
|
|
|
if($this->validCacheFileExists($_REQUEST['ieId'], 'messages', $filename)) { |
1830
|
|
|
$out = $this->getCacheValue($_REQUEST['ieId'], 'messages', $filename, 'out'); |
1831
|
|
|
$noCache = false; |
1832
|
|
|
|
1833
|
|
|
// something fubar'd the cache? |
1834
|
|
|
if(empty($out['meta']['email']['name']) && empty($out['meta']['email']['description'])) { |
1835
|
|
|
$noCache = true; |
1836
|
|
|
} else { |
1837
|
|
|
// When sending data from cache, convert date into users preffered format |
1838
|
|
|
$dateTimeInGMTFormat = $out['meta']['email']['date_start']; |
1839
|
|
|
$out['meta']['email']['date_start'] = $timedate->to_display_date_time($dateTimeInGMTFormat); |
1840
|
|
|
} // else |
1841
|
|
|
} |
1842
|
|
|
|
1843
|
|
|
if($noCache) { |
1844
|
|
|
$writeToCacheFile = true; |
1845
|
|
|
if ($ie->isPop3Protocol()) { |
1846
|
|
|
$status = $ie->setEmailForDisplay($_REQUEST['uid'], true, true, true); |
1847
|
|
|
} else { |
1848
|
|
|
$status = $ie->setEmailForDisplay($_REQUEST['uid'], false, true, true); |
1849
|
|
|
} |
1850
|
|
|
$out = $ie->displayOneEmail($_REQUEST['uid'], $_REQUEST['mbox']); |
1851
|
|
|
// modify the out object to store date in GMT format on the local cache file |
1852
|
|
|
$dateTimeInUserFormat = $out['meta']['email']['date_start']; |
1853
|
|
|
$out['meta']['email']['date_start'] = $timedate->to_db($dateTimeInUserFormat); |
1854
|
|
|
if ($status == 'error') { |
1855
|
|
|
$writeToCacheFile = false; |
1856
|
|
|
} |
1857
|
|
|
if ($writeToCacheFile) { |
1858
|
|
|
if ($ie->isPop3Protocol()) { |
1859
|
|
|
$this->writeCacheFile('out', $out, $_REQUEST['ieId'], 'messages', "{$_REQUEST['mbox']}{$md5uidl}.php"); |
1860
|
|
|
} else { |
1861
|
|
|
$this->writeCacheFile('out', $out, $_REQUEST['ieId'], 'messages', "{$_REQUEST['mbox']}{$_REQUEST['uid']}.php"); |
1862
|
|
|
} // else |
1863
|
|
|
// restore date in the users preferred format to be send on to UI for diaply |
1864
|
|
|
$out['meta']['email']['date_start'] = $dateTimeInUserFormat; |
1865
|
|
|
} // if |
1866
|
|
|
} |
1867
|
|
|
$out['meta']['email']['toaddrs'] = $this->generateExpandableAddrs($out['meta']['email']['toaddrs']); |
1868
|
|
|
if(!empty($out['meta']['email']['cc_addrs'])) { |
1869
|
|
|
$ccs = $this->generateExpandableAddrs($out['meta']['email']['cc_addrs']); |
1870
|
|
|
$out['meta']['cc'] = <<<eoq |
1871
|
|
|
<tr> |
1872
|
|
|
<td NOWRAP valign="top" class="displayEmailLabel"> |
1873
|
|
|
{$app_strings['LBL_EMAIL_CC']}: |
1874
|
|
|
</td> |
1875
|
|
|
<td class="displayEmailValue"> |
1876
|
|
|
{$ccs} |
1877
|
|
|
</td> |
1878
|
|
|
</tr> |
1879
|
|
|
eoq; |
1880
|
|
|
} |
1881
|
|
|
|
1882
|
|
|
if(empty($out['meta']['email']['description'])) |
1883
|
|
|
$out['meta']['email']['description'] = $mod_strings['LBL_EMPTY_EMAIL_BODY']; |
1884
|
|
|
|
1885
|
|
|
if($noCache) { |
1886
|
|
|
$GLOBALS['log']->debug("EMAILUI: getSingleMessage() NOT using cache file"); |
1887
|
|
|
} else { |
1888
|
|
|
$GLOBALS['log']->debug("EMAILUI: getSingleMessage() using cache file [ ".$_REQUEST['mbox'].$_REQUEST['uid'].".php ]"); |
1889
|
|
|
} |
1890
|
|
|
|
1891
|
|
|
$this->setReadFlag($_REQUEST['ieId'], $_REQUEST['mbox'], $_REQUEST['uid']); |
1892
|
|
|
return $out; |
1893
|
|
|
} |
1894
|
|
|
|
1895
|
|
|
|
1896
|
|
|
/** |
1897
|
|
|
* Returns the HTML for a list of emails in a given folder |
1898
|
|
|
* @param GUID $ieId GUID to InboundEmail instance |
1899
|
|
|
* @param string $mbox Mailbox path name in dot notation |
1900
|
|
|
* @param int $folderListCacheOffset Seconds for valid cache file |
1901
|
|
|
* @return string HTML render of list. |
1902
|
|
|
*/ |
1903
|
|
|
function getListEmails($ieId, $mbox, $folderListCacheOffset, $forceRefresh='false') { |
1904
|
|
|
global $sugar_config; |
1905
|
|
|
|
1906
|
|
|
|
1907
|
|
|
$ie = new InboundEmail(); |
1908
|
|
|
$ie->retrieve($ieId); |
1909
|
|
|
$list = $ie->displayFolderContents($mbox, $forceRefresh); |
|
|
|
|
1910
|
|
|
|
1911
|
|
|
return $list; |
1912
|
|
|
} |
1913
|
|
|
|
1914
|
|
|
/** |
1915
|
|
|
* Returns the templatized compose screen. Used by reply, forwards and draft status messages. |
1916
|
|
|
* @param object email Email bean in focus |
1917
|
|
|
*/ |
1918
|
|
|
function displayComposeEmail($email) { |
1919
|
|
|
global $locale; |
1920
|
|
|
global $current_user; |
1921
|
|
|
|
1922
|
|
|
|
1923
|
|
|
$ea = new SugarEmailAddress(); |
1924
|
|
|
|
1925
|
|
|
if(!empty($email)) { |
1926
|
|
|
$email->cids2Links(); |
1927
|
|
|
$description = (empty($email->description_html)) ? $email->description : $email->description_html; |
1928
|
|
|
} |
1929
|
|
|
|
1930
|
|
|
//Get the most complete address list availible for this email |
1931
|
|
|
$addresses = array('toAddresses' => 'to', 'ccAddresses' => 'cc', 'bccAddresses' => 'bcc'); |
1932
|
|
|
foreach($addresses as $var => $type) |
1933
|
|
|
{ |
1934
|
|
|
$$var = ""; |
1935
|
|
|
foreach (array("{$type}_addrs_names", "{$type}addrs", "{$type}_addrs") as $emailVar) |
1936
|
|
|
{ |
1937
|
|
|
if (!empty($email->$emailVar)) { |
1938
|
|
|
$$var = $email->$emailVar; |
1939
|
|
|
break; |
1940
|
|
|
} |
1941
|
|
|
} |
1942
|
|
|
} |
1943
|
|
|
|
1944
|
|
|
$ret = array(); |
1945
|
|
|
$ret['type'] = $email->type; |
1946
|
|
|
$ret['name'] = $email->name; |
1947
|
|
|
$ret['description'] = $description; |
1948
|
|
|
$ret['from'] = (isset($_REQUEST['composeType']) && $_REQUEST['composeType'] == 'forward') ? "" : $email->from_addr; |
1949
|
|
|
$ret['to'] = from_html($toAddresses); |
|
|
|
|
1950
|
|
|
$ret['uid'] = $email->id; |
1951
|
|
|
$ret['parent_name'] = $email->parent_name; |
1952
|
|
|
$ret['parent_type'] = $email->parent_type; |
1953
|
|
|
$ret['parent_id'] = $email->parent_id; |
1954
|
|
|
|
1955
|
|
|
if ($email->type == 'draft') { |
1956
|
|
|
$ret['cc'] = from_html($ccAddresses); |
|
|
|
|
1957
|
|
|
$ret['bcc'] = $bccAddresses; |
|
|
|
|
1958
|
|
|
} |
1959
|
|
|
// reply all |
1960
|
|
|
if(isset($_REQUEST['composeType']) && $_REQUEST['composeType'] == 'replyAll') { |
1961
|
|
|
$ret['cc'] = from_html($ccAddresses); |
|
|
|
|
1962
|
|
|
$ret['bcc'] = $bccAddresses; |
|
|
|
|
1963
|
|
|
|
1964
|
|
|
$userEmails = array(); |
1965
|
|
|
$userEmailsMeta = $ea->getAddressesByGUID($current_user->id, 'Users'); |
1966
|
|
|
foreach($userEmailsMeta as $emailMeta) { |
1967
|
|
|
$userEmails[] = from_html(strtolower(trim($emailMeta['email_address']))); |
1968
|
|
|
} |
1969
|
|
|
$userEmails[] = from_html(strtolower(trim($email->from_addr))); |
1970
|
|
|
|
1971
|
|
|
$ret['cc'] = from_html($email->cc_addrs); |
1972
|
|
|
$toAddresses = from_html($toAddresses); |
|
|
|
|
1973
|
|
|
$to = str_replace($this->addressSeparators, "::", $toAddresses); |
1974
|
|
|
$exTo = explode("::", $to); |
1975
|
|
|
|
1976
|
|
|
if(is_array($exTo)) { |
1977
|
|
|
foreach($exTo as $addr) { |
1978
|
|
|
$addr = strtolower(trim($addr)); |
1979
|
|
|
if(!in_array($addr, $userEmails)) { |
1980
|
|
|
if(!empty($ret['cc'])) { |
1981
|
|
|
$ret['cc'] = $ret['cc'].", "; |
1982
|
|
|
} |
1983
|
|
|
$ret['cc'] = $ret['cc'].trim($addr); |
1984
|
|
|
} |
1985
|
|
|
} |
1986
|
|
|
} elseif(!empty($exTo)) { |
1987
|
|
|
$exTo = trim($exTo); |
1988
|
|
|
if(!in_array($exTo, $userEmails)) { |
1989
|
|
|
$ret['cc'] = $ret['cc'].", ".$exTo; |
1990
|
|
|
} |
1991
|
|
|
} |
1992
|
|
|
} |
1993
|
|
|
return $ret; |
1994
|
|
|
} |
1995
|
|
|
/** |
1996
|
|
|
* Formats email body on reply/forward |
1997
|
|
|
* @param object email Email object in focus |
1998
|
|
|
* @param string type |
1999
|
|
|
* @return object email |
2000
|
|
|
*/ |
2001
|
|
|
function handleReplyType($email, $type) { |
2002
|
|
|
global $mod_strings; |
2003
|
|
|
$GLOBALS['log']->debug("****At Handle Reply Type: $type"); |
2004
|
|
|
switch($type) { |
2005
|
|
|
case "reply": |
2006
|
|
|
case "replyAll": |
2007
|
|
|
$header = $email->getReplyHeader(); |
2008
|
|
|
if(!preg_match('/^(re:)+/i', $email->name)) { |
2009
|
|
|
$email->name = "{$mod_strings['LBL_RE']} {$email->name}"; |
2010
|
|
|
} |
2011
|
|
|
if ($type == "reply") { |
2012
|
|
|
$email->cc_addrs = ""; |
2013
|
|
|
if (!empty($email->reply_to_addr)) { |
2014
|
|
|
$email->from_addr = $email->reply_to_addr; |
2015
|
|
|
} // if |
2016
|
|
|
} else { |
2017
|
|
|
if (!empty($email->reply_to_addr)) { |
2018
|
|
|
$email->to_addrs = $email->to_addrs . "," . $email->reply_to_addr; |
2019
|
|
|
} // if |
2020
|
|
|
} // else |
2021
|
|
|
break; |
2022
|
|
|
|
2023
|
|
|
case "forward": |
2024
|
|
|
$header = $email->getForwardHeader(); |
2025
|
|
|
if(!preg_match('/^(fw:)+/i', $email->name)) { |
2026
|
|
|
$email->name = "{$mod_strings['LBL_FW']} {$email->name}"; |
2027
|
|
|
} |
2028
|
|
|
$email->cc_addrs = ""; |
2029
|
|
|
break; |
2030
|
|
|
|
2031
|
|
|
case "replyCase": |
2032
|
|
|
$GLOBALS['log']->debug("EMAILUI: At reply case"); |
2033
|
|
|
$header = $email->getReplyHeader(); |
2034
|
|
|
|
2035
|
|
|
$myCase = new aCase(); |
2036
|
|
|
$myCase->retrieve($email->parent_id); |
2037
|
|
|
$myCaseMacro = $myCase->getEmailSubjectMacro(); |
2038
|
|
|
$email->parent_name = $myCase->name; |
2039
|
|
|
$GLOBALS['log']->debug("****Case # : {$myCase->case_number} macro: $myCaseMacro"); |
2040
|
|
|
if(!strpos($email->name, str_replace('%1',$myCase->case_number,$myCaseMacro))) { |
2041
|
|
|
$GLOBALS['log']->debug("Replacing"); |
2042
|
|
|
$email->name = str_replace('%1',$myCase->case_number,$myCaseMacro) . ' '. $email->name; |
2043
|
|
|
} |
2044
|
|
|
$email->name = "{$mod_strings['LBL_RE']} {$email->name}"; |
2045
|
|
|
break; |
2046
|
|
|
} |
2047
|
|
|
|
2048
|
|
|
$html = trim($email->description_html); |
2049
|
|
|
$plain = trim($email->description); |
2050
|
|
|
|
2051
|
|
|
$desc = (!empty($html)) ? $html : $plain; |
2052
|
|
|
|
2053
|
|
|
$email->description = $header.$email->quoteHtmlEmailForNewEmailUI($desc); |
2054
|
|
|
return $email; |
2055
|
|
|
|
2056
|
|
|
} |
2057
|
|
|
|
2058
|
|
|
/////////////////////////////////////////////////////////////////////////// |
2059
|
|
|
//// PRIVATE HELPERS |
2060
|
|
|
/** |
2061
|
|
|
* Generates a UNION query to get one list of users, contacts, leads, and |
2062
|
|
|
* prospects; used specifically for the addressBook |
2063
|
|
|
*/ |
2064
|
|
|
function _getPeopleUnionQuery($whereArr , $person) { |
2065
|
|
|
global $current_user , $app_strings; |
2066
|
|
|
global $db; |
2067
|
|
|
if(!isset($person) || $person === 'LBL_DROPDOWN_LIST_ALL'){ |
2068
|
|
|
$peopleTables = array("users", |
2069
|
|
|
"contacts", |
2070
|
|
|
"leads", |
2071
|
|
|
"prospects", |
2072
|
|
|
"accounts" |
2073
|
|
|
); |
2074
|
|
|
}else{ |
2075
|
|
|
$peopleTables = array($person); |
2076
|
|
|
} |
2077
|
|
|
$q = ''; |
2078
|
|
|
|
2079
|
|
|
$whereAdd = ""; |
2080
|
|
|
|
2081
|
|
|
foreach($whereArr as $column => $clause) { |
2082
|
|
|
if(!empty($whereAdd)) { |
2083
|
|
|
$whereAdd .= " AND "; |
2084
|
|
|
} |
2085
|
|
|
$clause = $current_user->db->quote($clause); |
2086
|
|
|
$whereAdd .= "{$column} LIKE '{$clause}%'"; |
2087
|
|
|
} |
2088
|
|
|
|
2089
|
|
|
|
2090
|
|
|
foreach($peopleTables as $table) { |
2091
|
|
|
$module = ucfirst($table); |
2092
|
|
|
$class = substr($module, 0, strlen($module) - 1); |
2093
|
|
|
require_once("modules/{$module}/{$class}.php"); |
2094
|
|
|
$person = new $class(); |
2095
|
|
|
if (!$person->ACLAccess('list')) { |
2096
|
|
|
continue; |
2097
|
|
|
} // if |
2098
|
|
|
$where = "({$table}.deleted = 0 AND eabr.primary_address = 1 AND {$table}.id <> '{$current_user->id}')"; |
2099
|
|
|
|
2100
|
|
|
if (ACLController::requireOwner($module, 'list')) { |
2101
|
|
|
$where = $where . " AND ({$table}.assigned_user_id = '{$current_user->id}')"; |
2102
|
|
|
} // if |
2103
|
|
|
if(!empty($whereAdd)) { |
2104
|
|
|
$where .= " AND ({$whereAdd})"; |
2105
|
|
|
} |
2106
|
|
|
|
2107
|
|
|
if ($person === 'accounts') { |
2108
|
|
|
$t = "SELECT {$table}.id, '' first_name, {$table}.name, eabr.primary_address, ea.email_address, '{$module}' module "; |
2109
|
|
|
} else { |
2110
|
|
|
$t = "SELECT {$table}.id, {$table}.first_name, {$table}.last_name, eabr.primary_address, ea.email_address, '{$module}' module "; |
2111
|
|
|
} |
2112
|
|
|
$t .= "FROM {$table} "; |
2113
|
|
|
$t .= "JOIN email_addr_bean_rel eabr ON ({$table}.id = eabr.bean_id and eabr.deleted=0) "; |
2114
|
|
|
$t .= "JOIN email_addresses ea ON (eabr.email_address_id = ea.id) "; |
2115
|
|
|
$t .= " WHERE {$where}"; |
2116
|
|
|
|
2117
|
|
|
/* BEGIN - SECURITY GROUPS */ |
2118
|
|
|
//this function may not even be used anymore. Seems like findEmailFromBeanIds is preferred now |
2119
|
|
|
if($person->bean_implements('ACL') && ACLController::requireSecurityGroup($module, 'list') ) |
2120
|
|
|
{ |
2121
|
|
|
require_once('modules/SecurityGroups/SecurityGroup.php'); |
2122
|
|
|
global $current_user; |
2123
|
|
|
$owner_where = $person->getOwnerWhere($current_user->id); |
2124
|
|
|
$group_where = SecurityGroup::getGroupWhere($table,$module,$current_user->id); |
2125
|
|
|
$t .= " AND (". $owner_where." or ".$group_where.") "; |
2126
|
|
|
} |
2127
|
|
|
/* END - SECURITY GROUPS */ |
2128
|
|
|
|
2129
|
|
|
|
2130
|
|
|
if(!empty($q)) { |
2131
|
|
|
$q .= "\n UNION ALL \n"; |
2132
|
|
|
} |
2133
|
|
|
|
2134
|
|
|
$q .= "({$t})"; |
2135
|
|
|
} |
2136
|
|
|
$countq = "SELECT count(people.id) c from ($q) people"; |
2137
|
|
|
$q .= "ORDER BY last_name"; |
2138
|
|
|
|
2139
|
|
|
return array('query' => $q, 'countQuery' => $countq); |
2140
|
|
|
} |
2141
|
|
|
|
2142
|
|
|
/** |
2143
|
|
|
* get emails of related bean for a given bean id |
2144
|
|
|
* @param $beanType |
2145
|
|
|
* @param $condition array of conditions inclued bean id |
2146
|
|
|
* @return array('query' => $q, 'countQuery' => $countq); |
|
|
|
|
2147
|
|
|
*/ |
2148
|
|
|
function getRelatedEmail($beanType, $whereArr, $relatedBeanInfoArr = ''){ |
2149
|
|
|
global $beanList, $current_user, $app_strings, $db; |
2150
|
|
|
$finalQuery = ''; |
2151
|
|
|
$searchBeans = null; |
2152
|
|
|
if($beanType === 'LBL_DROPDOWN_LIST_ALL') |
2153
|
|
|
$searchBeans = array("users", |
2154
|
|
|
"contacts", |
2155
|
|
|
"leads", |
2156
|
|
|
"prospects", |
2157
|
|
|
"accounts" |
2158
|
|
|
); |
2159
|
|
|
|
2160
|
|
|
if ($relatedBeanInfoArr == '' || empty($relatedBeanInfoArr['related_bean_type']) ) |
2161
|
|
|
{ |
2162
|
|
|
if ($searchBeans != null) |
2163
|
|
|
{ |
2164
|
|
|
$q = array(); |
2165
|
|
|
foreach ($searchBeans as $searchBean) |
2166
|
|
|
{ |
2167
|
|
|
$searchq = $this->findEmailFromBeanIds('', $searchBean, $whereArr); |
2168
|
|
|
if(!empty($searchq)) { |
2169
|
|
|
$q[] = "($searchq)"; |
2170
|
|
|
} |
2171
|
|
|
} |
2172
|
|
|
if (!empty($q)) |
2173
|
|
|
$finalQuery .= implode("\n UNION ALL \n", $q); |
2174
|
|
|
} |
2175
|
|
|
else |
2176
|
|
|
$finalQuery = $this->findEmailFromBeanIds('', $beanType, $whereArr); |
2177
|
|
|
} |
2178
|
|
|
else |
2179
|
|
|
{ |
2180
|
|
|
$class = $beanList[$relatedBeanInfoArr['related_bean_type']]; |
2181
|
|
|
$focus = new $class(); |
2182
|
|
|
$focus->retrieve($relatedBeanInfoArr['related_bean_id']); |
2183
|
|
|
if ($searchBeans != null) |
2184
|
|
|
{ |
2185
|
|
|
$q = array(); |
2186
|
|
|
foreach ($searchBeans as $searchBean) |
2187
|
|
|
{ |
2188
|
|
|
if ($focus->load_relationship($searchBean)) |
2189
|
|
|
{ |
2190
|
|
|
$data = $focus->$searchBean->get(); |
2191
|
|
|
if (count($data) != 0) |
2192
|
|
|
$q[] = '('.$this->findEmailFromBeanIds($data, $searchBean, $whereArr).')'; |
2193
|
|
|
} |
2194
|
|
|
} |
2195
|
|
|
if (!empty($q)) |
2196
|
|
|
$finalQuery .= implode("\n UNION ALL \n", $q); |
2197
|
|
|
} |
2198
|
|
|
else |
2199
|
|
|
{ |
2200
|
|
|
if ($focus->load_relationship($beanType)) |
2201
|
|
|
{ |
2202
|
|
|
$data = $focus->$beanType->get(); |
2203
|
|
|
if (count($data) != 0) |
2204
|
|
|
$finalQuery = $this->findEmailFromBeanIds($data, $beanType, $whereArr); |
2205
|
|
|
} |
2206
|
|
|
} |
2207
|
|
|
} |
2208
|
|
|
$countq = "SELECT count(people.id) c from ($finalQuery) people"; |
2209
|
|
|
return array('query' => $finalQuery, 'countQuery' => $countq); |
2210
|
|
|
} |
2211
|
|
|
|
2212
|
|
|
function findEmailFromBeanIds($beanIds, $beanType, $whereArr) { |
2213
|
|
|
global $current_user; |
2214
|
|
|
$q = ''; |
2215
|
|
|
$whereAdd = ""; |
2216
|
|
|
$relatedIDs = ''; |
2217
|
|
|
if ($beanIds != '') { |
2218
|
|
|
foreach ($beanIds as $key => $value) { |
2219
|
|
|
$beanIds[$key] = '\''.$value.'\''; |
2220
|
|
|
} |
2221
|
|
|
$relatedIDs = implode(',', $beanIds); |
2222
|
|
|
} |
2223
|
|
|
|
2224
|
|
|
if ($beanType == 'accounts') { |
2225
|
|
|
if (isset($whereArr['first_name'])) { |
2226
|
|
|
$whereArr['name'] = $whereArr['first_name']; |
2227
|
|
|
} |
2228
|
|
|
unset($whereArr['last_name']); |
2229
|
|
|
unset($whereArr['first_name']); |
2230
|
|
|
} |
2231
|
|
|
|
2232
|
|
|
foreach($whereArr as $column => $clause) { |
2233
|
|
|
if(!empty($whereAdd)) { |
2234
|
|
|
$whereAdd .= " OR "; |
2235
|
|
|
} |
2236
|
|
|
$clause = $current_user->db->quote($clause); |
2237
|
|
|
$whereAdd .= "{$column} LIKE '{$clause}%'"; |
2238
|
|
|
} |
2239
|
|
|
$table = $beanType; |
2240
|
|
|
$module = ucfirst($table); |
2241
|
|
|
$class = substr($module, 0, strlen($module) - 1); |
2242
|
|
|
require_once("modules/{$module}/{$class}.php"); |
2243
|
|
|
$person = new $class(); |
2244
|
|
|
if ($person->ACLAccess('list')) { |
2245
|
|
|
if ($relatedIDs != '') { |
2246
|
|
|
$where = "({$table}.deleted = 0 AND eabr.primary_address = 1 AND {$table}.id in ($relatedIDs))"; |
2247
|
|
|
} else { |
2248
|
|
|
$where = "({$table}.deleted = 0 AND eabr.primary_address = 1)"; |
2249
|
|
|
} |
2250
|
|
|
|
2251
|
|
|
if (ACLController::requireOwner($module, 'list')) { |
2252
|
|
|
$where = $where . " AND ({$table}.assigned_user_id = '{$current_user->id}')"; |
2253
|
|
|
} // if |
2254
|
|
|
if(!empty($whereAdd)) { |
2255
|
|
|
$where .= " AND ({$whereAdd})"; |
2256
|
|
|
} |
2257
|
|
|
|
2258
|
|
|
if ($beanType === 'accounts') { |
2259
|
|
|
$t = "SELECT {$table}.id, '' first_name, {$table}.name last_name, eabr.primary_address, ea.email_address, '{$module}' module "; |
2260
|
|
|
} else { |
2261
|
|
|
$t = "SELECT {$table}.id, {$table}.first_name, {$table}.last_name, eabr.primary_address, ea.email_address, '{$module}' module "; |
2262
|
|
|
} |
2263
|
|
|
|
2264
|
|
|
$t .= "FROM {$table} "; |
2265
|
|
|
$t .= "JOIN email_addr_bean_rel eabr ON ({$table}.id = eabr.bean_id and eabr.deleted=0) "; |
2266
|
|
|
$t .= "JOIN email_addresses ea ON (eabr.email_address_id = ea.id) "; |
2267
|
|
|
$t .= " WHERE {$where}"; |
2268
|
|
|
/* BEGIN - SECURITY GROUPS */ |
2269
|
|
|
//this function may not even be used anymore. Seems like findEmailFromBeanIds is preferred now |
2270
|
|
|
if($person->bean_implements('ACL') && ACLController::requireSecurityGroup($module, 'list') ) |
2271
|
|
|
{ |
2272
|
|
|
require_once('modules/SecurityGroups/SecurityGroup.php'); |
2273
|
|
|
global $current_user; |
2274
|
|
|
$owner_where = $person->getOwnerWhere($current_user->id); |
2275
|
|
|
$group_where = SecurityGroup::getGroupWhere($table,$module,$current_user->id); |
2276
|
|
|
$t .= " AND (". $owner_where." or ".$group_where.") "; |
2277
|
|
|
} |
2278
|
|
|
/* END - SECURITY GROUPS */ |
2279
|
|
|
|
2280
|
|
|
} // if |
2281
|
|
|
return $t; |
2282
|
|
|
} |
2283
|
|
|
|
2284
|
|
|
/** |
2285
|
|
|
* Cleans UID lists |
2286
|
|
|
* @param mixed $uids |
2287
|
|
|
* @param bool $returnString False will return an array |
2288
|
|
|
* @return mixed |
2289
|
|
|
*/ |
2290
|
|
|
function _cleanUIDList($uids, $returnString=false) { |
2291
|
|
|
global $app_strings; |
2292
|
|
|
$GLOBALS['log']->debug("_cleanUIDList: before - [ {$uids} ]"); |
2293
|
|
|
|
2294
|
|
|
if(!is_array($uids)) { |
2295
|
|
|
$returnString = true; |
2296
|
|
|
|
2297
|
|
|
$exUids = explode($app_strings['LBL_EMAIL_DELIMITER'], $uids); |
2298
|
|
|
$uids = $exUids; |
2299
|
|
|
} |
2300
|
|
|
|
2301
|
|
|
$cleanUids = array(); |
2302
|
|
|
foreach($uids as $uid) { |
2303
|
|
|
$cleanUids[$uid] = $uid; |
2304
|
|
|
} |
2305
|
|
|
|
2306
|
|
|
sort($cleanUids); |
2307
|
|
|
|
2308
|
|
|
if($returnString) { |
2309
|
|
|
$cleanImplode = implode($app_strings['LBL_EMAIL_DELIMITER'], $cleanUids); |
2310
|
|
|
$GLOBALS['log']->debug("_cleanUIDList: after - [ {$cleanImplode} ]"); |
2311
|
|
|
return $cleanImplode; |
2312
|
|
|
} |
2313
|
|
|
|
2314
|
|
|
return $cleanUids; |
2315
|
|
|
} |
2316
|
|
|
|
2317
|
|
|
/** |
2318
|
|
|
* Creates Mail folder |
2319
|
|
|
* |
2320
|
|
|
* @param object $user User in focus |
2321
|
|
|
* @param array $folder_params Array of parameters for folder creation |
2322
|
|
|
*/ |
2323
|
|
|
protected function createFolder($user, $folder_params) |
2324
|
|
|
{ |
2325
|
|
|
$folder = new SugarFolder(); |
2326
|
|
|
foreach ($folder_params as $key => $val) { |
2327
|
|
|
$folder->$key = $val; |
2328
|
|
|
} |
2329
|
|
|
|
2330
|
|
|
$folder->save(); |
2331
|
|
|
|
2332
|
|
|
return $folder; |
2333
|
|
|
} |
2334
|
|
|
|
2335
|
|
|
/** |
2336
|
|
|
* Creates defaults for the User |
2337
|
|
|
* @param object $user User in focus |
2338
|
|
|
*/ |
2339
|
|
|
public function preflightUser(&$user) |
2340
|
|
|
{ |
2341
|
|
|
global $mod_strings; |
2342
|
|
|
$folder_types = array(); |
2343
|
|
|
|
2344
|
|
|
$params = array( |
2345
|
|
|
// My Emails |
2346
|
|
|
"inbound" => array( |
2347
|
|
|
'name' => $mod_strings['LNK_MY_INBOX'], |
2348
|
|
|
'folder_type' => "inbound", |
2349
|
|
|
'has_child' => 1, |
2350
|
|
|
'dynamic_query' => $this->generateDynamicFolderQuery("inbound", $user->id), |
2351
|
|
|
'is_dynamic' => 1, |
2352
|
|
|
'created_by' => $user->id, |
2353
|
|
|
'modified_by' => $user->id, |
2354
|
|
|
), |
2355
|
|
|
// My Drafts |
2356
|
|
|
"draft" => array( |
2357
|
|
|
'name' => $mod_strings['LNK_MY_DRAFTS'], |
2358
|
|
|
'folder_type' => "draft", |
2359
|
|
|
'has_child' => 0, |
2360
|
|
|
'dynamic_query' => $this->generateDynamicFolderQuery("draft", $user->id), |
2361
|
|
|
'is_dynamic' => 1, |
2362
|
|
|
'created_by' => $user->id, |
2363
|
|
|
'modified_by' => $user->id, |
2364
|
|
|
), |
2365
|
|
|
// Sent Emails |
2366
|
|
|
"sent" => array( |
2367
|
|
|
'name' => $mod_strings['LNK_SENT_EMAIL_LIST'], |
2368
|
|
|
'folder_type' => "sent", |
2369
|
|
|
'has_child' => 0, |
2370
|
|
|
'dynamic_query' => $this->generateDynamicFolderQuery("sent", $user->id), |
2371
|
|
|
'is_dynamic' => 1, |
2372
|
|
|
'created_by' => $user->id, |
2373
|
|
|
'modified_by' => $user->id, |
2374
|
|
|
), |
2375
|
|
|
// Archived Emails |
2376
|
|
|
"archived" => array( |
2377
|
|
|
'name' => $mod_strings['LBL_LIST_TITLE_MY_ARCHIVES'], |
2378
|
|
|
'folder_type' => "archived", |
2379
|
|
|
'has_child' => 0, |
2380
|
|
|
'dynamic_query' => '', |
2381
|
|
|
'is_dynamic' => 1, |
2382
|
|
|
'created_by' => $user->id, |
2383
|
|
|
'modified_by' => $user->id, |
2384
|
|
|
), |
2385
|
|
|
); |
2386
|
|
|
|
2387
|
|
|
$q = "SELECT * FROM folders f WHERE f.created_by = '{$user->id}' AND f.deleted = 0 AND coalesce(" . $user->db->convert("f.folder_type", "length") . ",0) > 0"; |
2388
|
|
|
$r = $user->db->query($q); |
2389
|
|
|
|
2390
|
|
|
while ($row = $GLOBALS['db']->fetchByAssoc($r)) { |
2391
|
|
|
if ($row['folder_type'] == 'inbound') { |
2392
|
|
|
$parent_id = $row['id']; |
2393
|
|
|
} |
2394
|
|
|
if (!in_array($row['folder_type'], $folder_types)) { |
2395
|
|
|
array_push($folder_types, $row['folder_type']); |
2396
|
|
|
} |
2397
|
|
|
if (isset($params[$row['folder_type']])) { |
2398
|
|
|
unset($params[$row['folder_type']]); |
2399
|
|
|
} |
2400
|
|
|
} |
2401
|
|
|
|
2402
|
|
|
require_once("include/SugarFolders/SugarFolders.php"); |
2403
|
|
|
|
2404
|
|
|
foreach ($params as $type => $type_params) { |
2405
|
|
|
if ($type == "inbound") { |
2406
|
|
|
|
2407
|
|
|
$folder = $this->createFolder($user, $params[$type]); |
2408
|
|
|
|
2409
|
|
|
$parent_id = $folder->id; |
2410
|
|
|
|
2411
|
|
|
// handle the case where inbound folder was deleted, but other folders exist |
2412
|
|
|
if (count($folder_types) != 0) { |
2413
|
|
|
// This update query will exclude inbound parent, and any custom created folders. |
2414
|
|
|
// For others, it will update their parent_id for the current user. |
2415
|
|
|
$q = "UPDATE folders SET parent_folder = '".$parent_id. |
2416
|
|
|
"' WHERE folder_type IN ('draft', 'sent', 'archived') AND created_by = '".$user->id."'"; |
2417
|
|
|
$q = "UPDATE folders SET parent_folder = '".$parent_id. |
2418
|
|
|
"' WHERE folder_type IN ('draft', 'sent', 'archived') AND created_by = '".$user->id."'"; |
2419
|
|
|
$r = $user->db->query($q); |
2420
|
|
|
} |
2421
|
|
|
} else { |
2422
|
|
|
$params[$type]['parent_folder'] = $parent_id; |
2423
|
|
|
|
2424
|
|
|
$this->createFolder($user, $params[$type]); |
2425
|
|
|
} |
2426
|
|
|
} |
2427
|
|
|
} |
2428
|
|
|
|
2429
|
|
|
/** |
2430
|
|
|
* Parses the core dynamic folder query |
2431
|
|
|
* @param string $type 'inbound', 'draft', etc. |
2432
|
|
|
* @param string $userId |
2433
|
|
|
* @return string |
2434
|
|
|
*/ |
2435
|
|
|
function generateDynamicFolderQuery($type, $userId) { |
2436
|
|
|
$q = $this->coreDynamicFolderQuery; |
2437
|
|
|
|
2438
|
|
|
$status = $type; |
2439
|
|
|
|
2440
|
|
|
if($type == "sent") { |
2441
|
|
|
$type = "out"; |
2442
|
|
|
} |
2443
|
|
|
|
2444
|
|
|
$replacee = array("::TYPE::", "::STATUS::", "::USER_ID::"); |
2445
|
|
|
$replacer = array($type, $status, $userId); |
2446
|
|
|
|
2447
|
|
|
$ret = str_replace($replacee, $replacer, $q); |
2448
|
|
|
|
2449
|
|
|
if($type == 'inbound') { |
2450
|
|
|
$ret .= " AND status NOT IN ('sent', 'archived', 'draft') AND type NOT IN ('out', 'archived', 'draft')"; |
2451
|
|
|
} else { |
2452
|
|
|
$ret .= " AND status NOT IN ('archived') AND type NOT IN ('archived')"; |
2453
|
|
|
} |
2454
|
|
|
|
2455
|
|
|
return $ret; |
2456
|
|
|
} |
2457
|
|
|
|
2458
|
|
|
/** |
2459
|
|
|
* Preps the User's cache dir |
2460
|
|
|
*/ |
2461
|
|
|
function preflightUserCache() { |
2462
|
|
|
$path = clean_path($this->userCacheDir); |
2463
|
|
|
if(!file_exists($this->userCacheDir)) |
2464
|
|
|
mkdir_recursive($path); |
2465
|
|
|
|
2466
|
|
|
$files = findAllFiles($path, array()); |
2467
|
|
|
|
2468
|
|
|
foreach($files as $file) { |
2469
|
|
|
unlink($file); |
2470
|
|
|
} |
2471
|
|
|
} |
2472
|
|
|
|
2473
|
|
|
function clearInboundAccountCache($ieId) { |
2474
|
|
|
global $sugar_config; |
2475
|
|
|
$cacheRoot = sugar_cached("modules/Emails/{$ieId}"); |
2476
|
|
|
$files = findAllFiles($cacheRoot."/messages/", array()); |
2477
|
|
|
foreach($files as $file) { |
2478
|
|
|
unlink($file); |
2479
|
|
|
} // fn |
2480
|
|
|
$files = findAllFiles($cacheRoot."/attachments/", array()); |
2481
|
|
|
foreach($files as $file) { |
2482
|
|
|
unlink($file); |
2483
|
|
|
} // for |
2484
|
|
|
} // fn |
2485
|
|
|
|
2486
|
|
|
/** |
2487
|
|
|
* returns an array of EmailTemplates that the user has access to for the compose email screen |
2488
|
|
|
* @return array |
2489
|
|
|
*/ |
2490
|
|
|
function getEmailTemplatesArray() { |
2491
|
|
|
|
2492
|
|
|
global $app_strings; |
2493
|
|
|
|
2494
|
|
|
if(ACLController::checkAccess('EmailTemplates', 'list', true) && ACLController::checkAccess('EmailTemplates', 'view', true)) { |
2495
|
|
|
$et = new EmailTemplate(); |
2496
|
|
|
$etResult = $et->db->query($et->create_new_list_query('',"(type IS NULL OR type='' OR type='email')",array(),array(),'')); |
|
|
|
|
2497
|
|
|
$email_templates_arr = array('' => $app_strings['LBL_NONE']); |
2498
|
|
|
while($etA = $et->db->fetchByAssoc($etResult)) { |
2499
|
|
|
$email_templates_arr[$etA['id']] = $etA['name']; |
2500
|
|
|
} |
2501
|
|
|
} else { |
2502
|
|
|
$email_templates_arr = array('' => $app_strings['LBL_NONE']); |
2503
|
|
|
} |
2504
|
|
|
|
2505
|
|
|
return $email_templates_arr; |
2506
|
|
|
} |
2507
|
|
|
|
2508
|
|
|
function getFromAccountsArray($ie) { |
2509
|
|
|
global $current_user; |
2510
|
|
|
global $app_strings; |
2511
|
|
|
|
2512
|
|
|
$ieAccountsFull = $ie->retrieveAllByGroupIdWithGroupAccounts($current_user->id); |
2513
|
|
|
$ieAccountsFrom= array(); |
2514
|
|
|
|
2515
|
|
|
$oe = new OutboundEmail(); |
2516
|
|
|
$system = $oe->getSystemMailerSettings(); |
2517
|
|
|
$ret = $current_user->getUsersNameAndEmail(); |
2518
|
|
|
$ret['name'] = from_html($ret['name']); |
2519
|
|
|
$useMyAccountString = true; |
2520
|
|
|
|
2521
|
|
|
if(empty($ret['email'])) { |
2522
|
|
|
$systemReturn = $current_user->getSystemDefaultNameAndEmail(); |
2523
|
|
|
$ret['email'] = $systemReturn['email']; |
2524
|
|
|
$ret['name'] = from_html($systemReturn['name']); |
2525
|
|
|
$useMyAccountString = false; |
2526
|
|
|
} // if |
2527
|
|
|
|
2528
|
|
|
$myAccountString = ''; |
2529
|
|
|
if ($useMyAccountString) { |
2530
|
|
|
$myAccountString = " - {$app_strings['LBL_MY_ACCOUNT']}"; |
2531
|
|
|
} // if |
2532
|
|
|
|
2533
|
|
|
//Check to make sure that the user has set the associated inbound email account -> outbound account is active. |
2534
|
|
|
$showFolders = unserialize(base64_decode($current_user->getPreference('showFolders', 'Emails'))); |
2535
|
|
|
$sf = new SugarFolder(); |
2536
|
|
|
$groupSubs = $sf->getSubscriptions($current_user); |
2537
|
|
|
|
2538
|
|
|
foreach($ieAccountsFull as $k => $v) |
2539
|
|
|
{ |
2540
|
|
|
$personalSelected = (!empty($showFolders) && in_array($v->id, $showFolders)); |
2541
|
|
|
|
2542
|
|
|
$allowOutboundGroupUsage = $v->get_stored_options('allow_outbound_group_usage',FALSE); |
2543
|
|
|
$groupSelected = ( in_array($v->groupfolder_id, $groupSubs) && $allowOutboundGroupUsage); |
2544
|
|
|
$selected = ( $personalSelected || $groupSelected ); |
2545
|
|
|
|
2546
|
|
|
if(!$selected) |
2547
|
|
|
{ |
2548
|
|
|
$GLOBALS['log']->debug("Inbound Email {$v->name}, not selected and will not be available for selection within compose UI."); |
2549
|
|
|
continue; |
2550
|
|
|
} |
2551
|
|
|
|
2552
|
|
|
$name = $v->get_stored_options('from_name'); |
2553
|
|
|
$addr = $v->get_stored_options('from_addr'); |
2554
|
|
|
if ($name != null && $addr != null) { |
2555
|
|
|
$name = from_html($name); |
2556
|
|
|
if (!$v->is_personal) { |
2557
|
|
|
$ieAccountsFrom[] = array("value" => $v->id, "text" => "{$name} ({$addr}) - {$app_strings['LBL_EMAIL_UPPER_CASE_GROUP']}"); |
2558
|
|
|
} else { |
2559
|
|
|
$ieAccountsFrom[] = array("value" => $v->id, "text" => "{$name} ({$addr})"); |
2560
|
|
|
} // else |
2561
|
|
|
} // if |
2562
|
|
|
} // foreach |
2563
|
|
|
|
2564
|
|
|
|
2565
|
|
|
$userSystemOverride = $oe->getUsersMailerForSystemOverride($current_user->id); |
2566
|
|
|
//Substitute in the users system override if its available. |
2567
|
|
|
if($userSystemOverride != null) |
2568
|
|
|
$system = $userSystemOverride; |
2569
|
|
|
|
2570
|
|
|
if( !empty($system->mail_smtpserver) ) |
2571
|
|
|
{ |
2572
|
|
|
$admin = new Administration(); |
2573
|
|
|
$admin->retrieveSettings(); //retrieve all admin settings. |
2574
|
|
|
$ieAccountsFrom[] = array("value" => $system->id, "text" => |
2575
|
|
|
"{$ret['name']} ({$ret['email']}){$myAccountString}"); |
2576
|
|
|
} |
2577
|
|
|
|
2578
|
|
|
return $ieAccountsFrom; |
2579
|
|
|
} // fn |
2580
|
|
|
|
2581
|
|
|
/** |
2582
|
|
|
* This function will return all the accounts this user has access to based on the |
2583
|
|
|
* match of the emailId passed in as a parameter |
2584
|
|
|
* |
2585
|
|
|
* @param unknown_type $ie |
2586
|
|
|
* @return unknown |
2587
|
|
|
*/ |
2588
|
|
|
function getFromAllAccountsArray($ie, $ret) { |
2589
|
|
|
global $current_user; |
2590
|
|
|
global $app_strings; |
2591
|
|
|
|
2592
|
|
|
$ret['fromAccounts'] = array(); |
2593
|
|
|
if (!isset($ret['to']) && !empty($ret['from'])) { |
2594
|
|
|
$ret['fromAccounts']['status'] = false; |
2595
|
|
|
return $ret; |
2596
|
|
|
} |
2597
|
|
|
$ieAccountsFull = $ie->retrieveAllByGroupIdWithGroupAccounts($current_user->id); |
2598
|
|
|
$foundInPersonalAccounts = false; |
2599
|
|
|
$foundInGroupAccounts = false; |
2600
|
|
|
$foundInSystemAccounts = false; |
2601
|
|
|
|
2602
|
|
|
//$toArray = array(); |
2603
|
|
|
if ($ret['type'] == "draft") { |
2604
|
|
|
$toArray = explode(",", $ret['from']); |
2605
|
|
|
} else { |
2606
|
|
|
$toArray = $ie->email->email2ParseAddressesForAddressesOnly($ret['to']); |
2607
|
|
|
} // else |
2608
|
|
|
foreach($ieAccountsFull as $k => $v) { |
2609
|
|
|
$storedOptions = unserialize(base64_decode($v->stored_options)); |
2610
|
|
|
if ( array_search_insensitive($storedOptions['from_addr'], $toArray)) { |
2611
|
|
|
if ($v->is_personal) { |
2612
|
|
|
$foundInPersonalAccounts = true; |
2613
|
|
|
break; |
2614
|
|
|
} else { |
2615
|
|
|
$foundInGroupAccounts = true; |
2616
|
|
|
} // else |
2617
|
|
|
} // if |
2618
|
|
|
} // foreach |
2619
|
|
|
|
2620
|
|
|
$oe = new OutboundEmail(); |
2621
|
|
|
$system = $oe->getSystemMailerSettings(); |
2622
|
|
|
|
2623
|
|
|
$return = $current_user->getUsersNameAndEmail(); |
2624
|
|
|
$return['name'] = from_html($return['name']); |
2625
|
|
|
$useMyAccountString = true; |
2626
|
|
|
|
2627
|
|
|
if(empty($return['email'])) { |
2628
|
|
|
$systemReturn = $current_user->getSystemDefaultNameAndEmail(); |
2629
|
|
|
$return['email'] = $systemReturn['email']; |
2630
|
|
|
$return['name'] = from_html($systemReturn['name']); |
2631
|
|
|
$useMyAccountString = false; |
2632
|
|
|
} // if |
2633
|
|
|
|
2634
|
|
|
$myAccountString = ''; |
2635
|
|
|
if ($useMyAccountString) { |
2636
|
|
|
$myAccountString = " - {$app_strings['LBL_MY_ACCOUNT']}"; |
2637
|
|
|
} // if |
2638
|
|
|
|
2639
|
|
|
if(!empty($system->id)) { |
2640
|
|
|
|
2641
|
|
|
$admin = new Administration(); |
2642
|
|
|
$admin->retrieveSettings(); //retrieve all admin settings. |
2643
|
|
|
if (in_array(trim($return['email']), $toArray)) { |
2644
|
|
|
$foundInSystemAccounts = true; |
2645
|
|
|
} // if |
2646
|
|
|
} // if |
2647
|
|
|
|
2648
|
|
|
if (!$foundInPersonalAccounts && !$foundInGroupAccounts && !$foundInSystemAccounts) { |
2649
|
|
|
$ret['fromAccounts']['status'] = false; |
2650
|
|
|
return $ret; |
2651
|
|
|
} // if |
2652
|
|
|
|
2653
|
|
|
$ieAccountsFrom= array(); |
2654
|
|
|
foreach($ieAccountsFull as $k => $v) { |
2655
|
|
|
$storedOptions = unserialize(base64_decode($v->stored_options)); |
2656
|
|
|
$storedOptionsName = from_html($storedOptions['from_name']); |
2657
|
|
|
|
2658
|
|
|
$selected = false; |
2659
|
|
|
if (array_search_insensitive($storedOptions['from_addr'], $toArray)) { |
2660
|
|
|
//if ($ret['to'] == $storedOptions['from_addr']) { |
2661
|
|
|
$selected = true; |
2662
|
|
|
} // if |
2663
|
|
|
if ($foundInPersonalAccounts) { |
2664
|
|
|
if ($v->is_personal) { |
2665
|
|
|
$ieAccountsFrom[] = array("value" => $v->id, "selected" => $selected, "text" => "{$storedOptionsName} ({$storedOptions['from_addr']})"); |
2666
|
|
|
} // if |
2667
|
|
|
} else { |
2668
|
|
|
$ieAccountsFrom[] = array("value" => $v->id, "selected" => $selected, "text" => "{$storedOptionsName} ({$storedOptions['from_addr']}) - {$app_strings['LBL_EMAIL_UPPER_CASE_GROUP']}"); |
2669
|
|
|
} // else |
2670
|
|
|
} // foreach |
2671
|
|
|
|
2672
|
|
|
if(!empty($system->id)) { |
2673
|
|
|
if (!$foundInPersonalAccounts && !$foundInGroupAccounts && $foundInSystemAccounts) { |
2674
|
|
|
$ieAccountsFrom[] = array("value" => $system->id, "selected" => true, "text" => |
2675
|
|
|
"{$return['name']} ({$return['email']}){$myAccountString}"); |
2676
|
|
|
} else { |
2677
|
|
|
$ieAccountsFrom[] = array("value" => $system->id, "text" => |
2678
|
|
|
"{$return['name']} ({$return['email']}){$myAccountString}"); |
2679
|
|
|
} // else |
2680
|
|
|
} // if |
2681
|
|
|
|
2682
|
|
|
$ret['fromAccounts']['status'] = ($foundInPersonalAccounts || $foundInGroupAccounts || $foundInSystemAccounts) ? true : false; |
2683
|
|
|
$ret['fromAccounts']['data'] = $ieAccountsFrom; |
2684
|
|
|
return $ret; |
2685
|
|
|
} // fn |
2686
|
|
|
|
2687
|
|
|
|
2688
|
|
|
/** |
2689
|
|
|
* takes an array and creates XML |
2690
|
|
|
* @param array Array to convert |
2691
|
|
|
* @param string Name to wrap highest level items in array |
2692
|
|
|
* @return string XML |
2693
|
|
|
*/ |
2694
|
|
|
function arrayToXML($a, $paramName) { |
2695
|
|
|
if(!is_array($a)) |
2696
|
|
|
return ''; |
2697
|
|
|
|
2698
|
|
|
$bad = array("<",">","'",'"',"&"); |
2699
|
|
|
$good = array("<", ">", "'", ""","&"); |
2700
|
|
|
|
2701
|
|
|
$ret = ""; |
2702
|
|
|
|
2703
|
|
|
for($i=0; $i<count($a); $i++) { |
|
|
|
|
2704
|
|
|
$email = $a[$i]; |
2705
|
|
|
$ret .= "\n<{$paramName}>"; |
2706
|
|
|
|
2707
|
|
|
foreach($email as $k => $v) { |
2708
|
|
|
$ret .= "\n\t<{$k}>".str_replace($bad, $good, $v)."</{$k}>"; |
2709
|
|
|
} |
2710
|
|
|
$ret .= "\n</{$paramName}>"; |
2711
|
|
|
} |
2712
|
|
|
return $ret; |
2713
|
|
|
} |
2714
|
|
|
|
2715
|
|
|
/** |
2716
|
|
|
* Re-used option getter for Show Accounts multiselect pane |
2717
|
|
|
*/ |
2718
|
|
|
function getShowAccountsOptions(&$ie) { |
2719
|
|
|
global $current_user; |
2720
|
|
|
global $app_strings; |
2721
|
|
|
global $mod_strings; |
2722
|
|
|
|
2723
|
|
|
$ieAccountsFull = $ie->retrieveAllByGroupId($current_user->id); |
2724
|
|
|
$ieAccountsShowOptionsMeta = array(); |
2725
|
|
|
$showFolders = unserialize(base64_decode($current_user->getPreference('showFolders', 'Emails'))); |
2726
|
|
|
|
2727
|
|
|
$defaultIEAccount = $ie->getUsersDefaultOutboundServerId($current_user); |
2728
|
|
|
|
2729
|
|
|
foreach($ieAccountsFull as $k => $v) { |
2730
|
|
|
$selected = (!empty($showFolders) && in_array($v->id, $showFolders)) ? true : false; |
2731
|
|
|
$default = ($defaultIEAccount == $v->id) ? TRUE : FALSE; |
2732
|
|
|
$has_groupfolder = !empty($v->groupfolder_id) ? TRUE : FALSE; |
2733
|
|
|
$type = ($v->is_personal) ? $mod_strings['LBL_MAILBOX_TYPE_PERSONAL'] : $mod_strings['LBL_MAILBOX_TYPE_GROUP']; |
2734
|
|
|
|
2735
|
|
|
$ieAccountsShowOptionsMeta[] = array("id" => $v->id, "name" => $v->name, 'is_active' => $selected, |
2736
|
|
|
'server_url' => $v->server_url, 'is_group' => !$v->is_personal,'group_id' => $v->group_id, |
2737
|
|
|
'is_default' => $default, 'has_groupfolder' => $has_groupfolder,'type' => $type ); |
2738
|
|
|
} |
2739
|
|
|
|
2740
|
|
|
//Retrieve the grou folders |
2741
|
|
|
$f = new SugarFolder(); |
2742
|
|
|
$groupFolders = $f->getGroupFoldersForSettings($current_user); |
2743
|
|
|
|
2744
|
|
|
foreach ($groupFolders as $singleGroup) |
2745
|
|
|
{ |
2746
|
|
|
//Retrieve the related IE accounts. |
2747
|
|
|
$relatedIEAccounts = $ie->retrieveByGroupFolderId($singleGroup['id']); |
2748
|
|
|
|
2749
|
|
|
if(count($relatedIEAccounts) == 0) |
2750
|
|
|
$server_url = $app_strings['LBL_EMAIL_MULT_GROUP_FOLDER_ACCOUNTS_EMPTY']; |
2751
|
|
|
else if(count($relatedIEAccounts) == 1) |
2752
|
|
|
{ |
2753
|
|
|
if($relatedIEAccounts[0]->status != 'Active' || $relatedIEAccounts[0]->mailbox_type == 'bounce') |
2754
|
|
|
continue; |
2755
|
|
|
|
2756
|
|
|
$server_url = $relatedIEAccounts[0]->server_url; |
2757
|
|
|
} |
2758
|
|
|
else |
2759
|
|
|
$server_url = $app_strings['LBL_EMAIL_MULT_GROUP_FOLDER_ACCOUNTS']; |
2760
|
|
|
|
2761
|
|
|
$type = $mod_strings['LBL_MAILBOX_TYPE_GROUP_FOLDER']; |
2762
|
|
|
$ieAccountsShowOptionsMeta[] = array("id" => $singleGroup['id'], "name" => $singleGroup['origName'], 'is_active' => $singleGroup['selected'], |
2763
|
|
|
'server_url' => $server_url, 'is_group' => true,'group_id' => $singleGroup['id'], |
2764
|
|
|
'is_default' => FALSE, 'has_groupfolder' => true,'type' => $type); |
2765
|
|
|
} |
2766
|
|
|
|
2767
|
|
|
|
2768
|
|
|
return $ieAccountsShowOptionsMeta; |
2769
|
|
|
} |
2770
|
|
|
|
2771
|
|
|
function getShowAccountsOptionsForSearch(&$ie) { |
2772
|
|
|
global $current_user; |
2773
|
|
|
global $app_strings; |
2774
|
|
|
|
2775
|
|
|
$ieAccountsFull = $ie->retrieveAllByGroupId($current_user->id); |
2776
|
|
|
//$ieAccountsShowOptions = "<option value=''>{$app_strings['LBL_NONE']}</option>\n"; |
2777
|
|
|
$ieAccountsShowOptionsMeta = array(); |
2778
|
|
|
$ieAccountsShowOptionsMeta[] = array("value" => "", "text" => $app_strings['LBL_NONE'], 'selected' => ''); |
2779
|
|
|
$showFolders = unserialize(base64_decode($current_user->getPreference('showFolders', 'Emails'))); |
2780
|
|
|
|
2781
|
|
|
foreach($ieAccountsFull as $k => $v) { |
2782
|
|
|
if(!in_array($v->id, $showFolders)) { |
2783
|
|
|
continue; |
2784
|
|
|
} |
2785
|
|
|
$group = (!$v->is_personal) ? $app_strings['LBL_EMAIL_GROUP']."." : ""; |
2786
|
|
|
$ieAccountsShowOptionsMeta[] = array("value" => $v->id, "text" => $group.$v->name, 'protocol' => $v->protocol); |
2787
|
|
|
} |
2788
|
|
|
|
2789
|
|
|
return $ieAccountsShowOptionsMeta; |
2790
|
|
|
} |
2791
|
|
|
/** |
2792
|
|
|
* Formats a display message on successful async call |
2793
|
|
|
* @param string $type Type of message to display |
2794
|
|
|
*/ |
2795
|
|
|
function displaySuccessMessage($type) { |
2796
|
|
|
global $app_strings; |
2797
|
|
|
|
2798
|
|
|
switch($type) { |
2799
|
|
|
case "delete": |
2800
|
|
|
$message = $app_strings['LBL_EMAIL_DELETE_SUCCESS']; |
2801
|
|
|
break; |
2802
|
|
|
|
2803
|
|
|
default: |
2804
|
|
|
$message = "NOOP: invalid type"; |
2805
|
|
|
break; |
2806
|
|
|
} |
2807
|
|
|
|
2808
|
|
|
$this->smarty->assign('app_strings', $app_strings); |
2809
|
|
|
$this->smarty->assign('message', $message); |
2810
|
|
|
echo $this->smarty->fetch("modules/Emails/templates/successMessage.tpl"); |
2811
|
|
|
} |
2812
|
|
|
|
2813
|
|
|
/** |
2814
|
|
|
* Validates existence and expiration of a cache file |
2815
|
|
|
* @param string $ieId |
2816
|
|
|
* @param string $type Type of cache file: folders, messages, etc. |
2817
|
|
|
* @param string $file The cachefile name |
2818
|
|
|
* @param int refreshOffset Refresh time in secs. |
2819
|
|
|
* @return mixed. |
|
|
|
|
2820
|
|
|
*/ |
2821
|
|
|
function validCacheFileExists($ieId, $type, $file, $refreshOffset=-1) { |
2822
|
|
|
global $sugar_config; |
2823
|
|
|
|
2824
|
|
|
if($refreshOffset == -1) { |
2825
|
|
|
$refreshOffset = $this->cacheTimeouts[$type]; // use defaults |
2826
|
|
|
} |
2827
|
|
|
|
2828
|
|
|
$cacheFilePath = sugar_cached("modules/Emails/{$ieId}/{$type}/{$file}"); |
2829
|
|
|
if(file_exists($cacheFilePath)) { |
2830
|
|
|
return true; |
2831
|
|
|
} |
2832
|
|
|
|
2833
|
|
|
return false; |
2834
|
|
|
} |
2835
|
|
|
|
2836
|
|
|
/** |
2837
|
|
|
* retrieves the cached value |
2838
|
|
|
* @param string $ieId |
2839
|
|
|
* @param string $type Type of cache file: folders, messages, etc. |
2840
|
|
|
* @param string $file The cachefile name |
2841
|
|
|
* @param string $key name of cache value |
2842
|
|
|
* @return mixed |
2843
|
|
|
*/ |
2844
|
|
|
function getCacheValue($ieId, $type, $file, $key) { |
2845
|
|
|
global $sugar_config; |
2846
|
|
|
|
2847
|
|
|
$cleanIeId = cleanDirName($ieId); |
2848
|
|
|
$cleanType = cleanDirName($type); |
2849
|
|
|
$cleanFile = cleanFileName($file); |
2850
|
|
|
$cacheFilePath = sugar_cached("modules/Emails/{$cleanIeId}/{$cleanType}/{$cleanFile}"); |
2851
|
|
|
$cacheFile = array(); |
2852
|
|
|
|
2853
|
|
|
if(file_exists($cacheFilePath)) { |
2854
|
|
|
include($cacheFilePath); // provides $cacheFile |
2855
|
|
|
|
2856
|
|
|
if(isset($cacheFile[$key])) { |
2857
|
|
|
$ret = unserialize($cacheFile[$key]); |
2858
|
|
|
return $ret; |
2859
|
|
|
} |
2860
|
|
|
} else { |
2861
|
|
|
$GLOBALS['log']->debug("EMAILUI: cache file not found [ {$cacheFilePath} ] - creating blank cache file"); |
2862
|
|
|
$this->writeCacheFile('retArr', array(), $ieId, $type, $file); |
2863
|
|
|
} |
2864
|
|
|
|
2865
|
|
|
return null; |
2866
|
|
|
} |
2867
|
|
|
|
2868
|
|
|
/** |
2869
|
|
|
* retrieves the cache file last touched time |
2870
|
|
|
* @param string $ieId |
2871
|
|
|
* @param string $type Type of cache file: folders, messages, etc. |
2872
|
|
|
* @param string $file The cachefile name |
2873
|
|
|
* @return string |
2874
|
|
|
*/ |
2875
|
|
|
function getCacheTimestamp($ieId, $type, $file) { |
2876
|
|
|
global $sugar_config; |
2877
|
|
|
|
2878
|
|
|
$cacheFilePath = sugar_cached("modules/Emails/{$ieId}/{$type}/{$file}"); |
2879
|
|
|
$cacheFile = array(); |
2880
|
|
|
|
2881
|
|
|
if(file_exists($cacheFilePath)) { |
2882
|
|
|
include($cacheFilePath); // provides $cacheFile['timestamp'] |
2883
|
|
|
|
2884
|
|
|
if(isset($cacheFile['timestamp'])) { |
2885
|
|
|
$GLOBALS['log']->debug("EMAILUI: found timestamp [ {$cacheFile['timestamp']} ]"); |
2886
|
|
|
return $cacheFile['timestamp']; |
2887
|
|
|
} |
2888
|
|
|
} |
2889
|
|
|
|
2890
|
|
|
return ''; |
2891
|
|
|
} |
2892
|
|
|
|
2893
|
|
|
/** |
2894
|
|
|
* Updates the timestamp for a cache file - usually to mark a "check email" |
2895
|
|
|
* process |
2896
|
|
|
* @param string $ieId |
2897
|
|
|
* @param string $type Type of cache file: folders, messages, etc. |
2898
|
|
|
* @param string $file The cachefile name |
2899
|
|
|
*/ |
2900
|
|
|
function setCacheTimestamp($ieId, $type, $file) { |
2901
|
|
|
global $sugar_config; |
2902
|
|
|
|
2903
|
|
|
$cacheFilePath = sugar_cached("modules/Emails/{$ieId}/{$type}/{$file}"); |
2904
|
|
|
$cacheFile = array(); |
2905
|
|
|
|
2906
|
|
|
if(file_exists($cacheFilePath)) { |
2907
|
|
|
include($cacheFilePath); // provides $cacheFile['timestamp'] |
2908
|
|
|
|
2909
|
|
|
if(isset($cacheFile['timestamp'])) { |
2910
|
|
|
$cacheFile['timestamp'] = strtotime('now'); |
2911
|
|
|
$GLOBALS['log']->debug("EMAILUI: setting updated timestamp [ {$cacheFile['timestamp']} ]"); |
2912
|
|
|
return $this->_writeCacheFile($cacheFile, $cacheFilePath); |
2913
|
|
|
} |
2914
|
|
|
} |
2915
|
|
|
} |
2916
|
|
|
|
2917
|
|
|
|
2918
|
|
|
/** |
2919
|
|
|
* Writes caches to flat file in cache dir. |
2920
|
|
|
* @param string $key Key to the main cache entry (not timestamp) |
2921
|
|
|
* @param mixed $var Variable to be cached |
2922
|
|
|
* @param string $ieId I-E focus ID |
2923
|
|
|
* @param string $type Folder in cache |
2924
|
|
|
* @param string $file Cache file name |
2925
|
|
|
*/ |
2926
|
|
|
function writeCacheFile($key, $var, $ieId, $type, $file) { |
2927
|
|
|
global $sugar_config; |
2928
|
|
|
|
2929
|
|
|
$cleanIeId = cleanDirName($ieId); |
2930
|
|
|
$cleanType = cleanDirName($type); |
2931
|
|
|
$cleanFile = cleanFileName($file); |
2932
|
|
|
$the_file = sugar_cached("modules/Emails/{$cleanIeId}/{$cleanType}/{$cleanFile}"); |
2933
|
|
|
$timestamp = strtotime('now'); |
2934
|
|
|
$array = array(); |
2935
|
|
|
$array['timestamp'] = $timestamp; |
2936
|
|
|
$array[$key] = serialize($var); // serialized since varexport_helper() can't handle PHP objects |
2937
|
|
|
|
2938
|
|
|
return $this->_writeCacheFile($array, $the_file); |
2939
|
|
|
} |
2940
|
|
|
|
2941
|
|
|
/** |
2942
|
|
|
* Performs the actual file write. Abstracted from writeCacheFile() for |
2943
|
|
|
* flexibility |
2944
|
|
|
* @param array $array The array to write to the cache |
2945
|
|
|
* @param string $file Full path (relative) with cache file name |
2946
|
|
|
* @return bool |
2947
|
|
|
*/ |
2948
|
|
|
function _writeCacheFile($array, $file) { |
2949
|
|
|
global $sugar_config; |
2950
|
|
|
|
2951
|
|
|
$arrayString = var_export_helper($array); |
2952
|
|
|
|
2953
|
|
|
$date = date("r"); |
2954
|
|
|
$the_string =<<<eoq |
2955
|
|
|
<?php // created: {$date} |
2956
|
|
|
\$cacheFile = {$arrayString}; |
2957
|
|
|
?> |
2958
|
|
|
eoq; |
2959
|
|
|
if($fh = @sugar_fopen($file, "w")) { |
2960
|
|
|
fputs($fh, $the_string); |
2961
|
|
|
fclose($fh); |
2962
|
|
|
return true; |
2963
|
|
|
} else { |
2964
|
|
|
$GLOBALS['log']->debug("EMAILUI: Could not write cache file [ {$file} ]"); |
2965
|
|
|
return false; |
2966
|
|
|
} |
2967
|
|
|
} |
2968
|
|
|
|
2969
|
|
|
/** |
2970
|
|
|
* Generate JSON encoded data to be consumed by yui datatable. |
2971
|
|
|
* |
2972
|
|
|
* @param array $data |
2973
|
|
|
* @param string $resultsParam The resultsList name |
2974
|
|
|
* @return string |
2975
|
|
|
*/ |
2976
|
|
|
function jsonOuput($data, $resultsParam, $count=0, $fromCache=true, $unread=-1) { |
2977
|
|
|
global $app_strings; |
2978
|
|
|
|
2979
|
|
|
$count = ($count > 0) ? $count : 0; |
2980
|
|
|
|
2981
|
|
|
if(isset($a['fromCache'])) |
|
|
|
|
2982
|
|
|
$cached = ($a['fromCache'] == 1) ? 1 : 0; |
2983
|
|
|
else |
2984
|
|
|
$cached = ($fromCache) ? 1 : 0; |
2985
|
|
|
|
2986
|
|
|
if($data['mbox'] == 'undefined' || empty($data['mbox'])) |
2987
|
|
|
$data['mbox'] = $app_strings['LBL_NONE']; |
2988
|
|
|
|
2989
|
|
|
$jsonOut = array('TotalCount' => $count, 'FromCache' => $cached, 'UnreadCount' => $unread, $resultsParam => $data['out']); |
2990
|
|
|
|
2991
|
|
|
return json_encode($jsonOut); |
2992
|
|
|
} |
2993
|
|
|
/** |
2994
|
|
|
* generates XML output from an array |
2995
|
|
|
* @param array |
2996
|
|
|
* @param string master list Item |
2997
|
|
|
* @return string |
2998
|
|
|
*/ |
2999
|
|
|
function xmlOutput($a, $paramName, $count=0, $fromCache=true, $unread=-1) { |
3000
|
|
|
global $app_strings; |
3001
|
|
|
$count = ($count > 0) ? $count : 0; |
3002
|
|
|
|
3003
|
|
|
if(isset($a['fromCache'])) { |
3004
|
|
|
$cached = ($a['fromCache'] == 1) ? 1 : 0; |
3005
|
|
|
} else { |
3006
|
|
|
$cached = ($fromCache) ? 1 : 0; |
3007
|
|
|
} |
3008
|
|
|
|
3009
|
|
|
if($a['mbox'] == 'undefined' || empty($a['mbox'])) { |
3010
|
|
|
$a['mbox'] = $app_strings['LBL_NONE']; |
3011
|
|
|
} |
3012
|
|
|
|
3013
|
|
|
$xml = $this->arrayToXML($a['out'], $paramName); |
3014
|
|
|
|
3015
|
|
|
$ret =<<<eoq |
3016
|
|
|
<?xml version="1.0" encoding="UTF-8"?> |
3017
|
|
|
<EmailPage> |
3018
|
|
|
<TotalCount>{$count}</TotalCount> |
3019
|
|
|
<UnreadCount>{$unread}</UnreadCount> |
3020
|
|
|
<FromCache> {$cached} </FromCache> |
3021
|
|
|
<{$paramName}s> |
3022
|
|
|
{$xml} |
3023
|
|
|
</{$paramName}s> |
3024
|
|
|
</EmailPage> |
3025
|
|
|
eoq; |
3026
|
|
|
return $ret; |
3027
|
|
|
} |
3028
|
|
|
|
3029
|
|
|
/** |
3030
|
|
|
* Generate to/cc addresses string in email detailview. |
3031
|
|
|
* |
3032
|
|
|
* @param string $str |
3033
|
|
|
* @param string $target values: to, cc |
|
|
|
|
3034
|
|
|
* @param int $defaultNum |
|
|
|
|
3035
|
|
|
* @return string $str |
3036
|
|
|
*/ |
3037
|
|
|
function generateExpandableAddrs($str) { |
3038
|
|
|
global $mod_strings; |
3039
|
|
|
$tempStr = $str.','; |
3040
|
|
|
$tempStr = html_entity_decode($tempStr); |
3041
|
|
|
$tempStr = $this->unifyEmailString($tempStr); |
3042
|
|
|
$defaultNum = 2; |
3043
|
|
|
$pattern = '/@.*,/U'; |
3044
|
|
|
preg_match_all($pattern, $tempStr, $matchs); |
3045
|
|
|
$totalCount = count($matchs[0]); |
3046
|
|
|
|
3047
|
|
|
if(!empty($matchs[0]) && $totalCount > $defaultNum) { |
3048
|
|
|
$position = strpos($tempStr, $matchs[0][$defaultNum]); |
3049
|
|
|
$hiddenCount = $totalCount - $defaultNum; |
3050
|
|
|
$frontStr = substr($tempStr, 0, $position); |
3051
|
|
|
$backStr = substr($tempStr, $position, -1); |
3052
|
|
|
$str = htmlentities($frontStr) . '<a class="utilsLink" onclick="javascript: SUGAR.email2.detailView.displayAllAddrs(this);">...['.$mod_strings['LBL_EMAIL_DETAIL_VIEW_SHOW'].$hiddenCount.$mod_strings['LBL_EMAIL_DETAIL_VIEW_MORE'].']</a><span style="display: none;">' .htmlentities($backStr).'</span>'; |
3053
|
|
|
} |
3054
|
|
|
|
3055
|
|
|
return $str; |
3056
|
|
|
} |
3057
|
|
|
|
3058
|
|
|
/** |
3059
|
|
|
* Unify the seperator as , |
3060
|
|
|
* |
3061
|
|
|
* @param String $str email address string |
3062
|
|
|
* @return String converted string |
3063
|
|
|
*/ |
3064
|
|
|
function unifyEmailString($str) { |
3065
|
|
|
preg_match_all('/@.*;/U', $str, $matches); |
3066
|
|
|
if(!empty($matches[0])) { |
3067
|
|
|
foreach($matches[0] as $key => $value) { |
3068
|
|
|
$new[] = str_replace(";",",",$value); |
3069
|
|
|
} |
3070
|
|
|
return str_replace($matches[0], $new, $str); |
3071
|
|
|
} |
3072
|
|
|
return $str; |
3073
|
|
|
} |
3074
|
|
|
} // end class def |
3075
|
|
|
|
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.
If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.
In this case you can add the
@ignore
PhpDoc annotation to the duplicate definition and it will be ignored.