1: <?php
2:
3: /**
4: * Core modules
5: * @package modules
6: * @subpackage core
7: */
8:
9: /**
10: * get basic message list settings
11: * @subpackage core/functions
12: * @param string $path message list path
13: * @param object $handler hm handler module
14: * @return array
15: */
16: if (!hm_exists('get_message_list_settings')) {
17: function get_message_list_settings($path, $handler) {
18: $list_path = $path;
19: $mailbox_list_title = array();
20: $message_list_since = DEFAULT_SINCE;
21: $per_source_limit = DEFAULT_PER_SOURCE;
22:
23: if ($path == 'unread') {
24: $list_path = 'unread';
25: $mailbox_list_title = array('Unread');
26: $message_list_since = $handler->user_config->get('unread_since_setting', DEFAULT_UNREAD_SINCE);
27: $per_source_limit = $handler->user_config->get('unread_per_source_setting', DEFAULT_UNREAD_PER_SOURCE);
28: }
29: elseif ($path == 'email') {
30: $message_list_since = $handler->user_config->get('all_email_since_setting', DEFAULT_ALL_EMAIL_SINCE);
31: $per_source_limit = $handler->user_config->get('all_email_per_source_setting', DEFAULT_ALL_EMAIL_PER_SOURCE);
32: $list_path = 'email';
33: $mailbox_list_title = array('All Email');
34: }
35: elseif ($path == 'flagged') {
36: $list_path = 'flagged';
37: $message_list_since = $handler->user_config->get('flagged_since_setting', DEFAULT_FLAGGED_SINCE);
38: $per_source_limit = $handler->user_config->get('flagged_per_source_setting', DEFAULT_FLAGGED_PER_SOURCE);
39: $mailbox_list_title = array('Flagged');
40: }
41: elseif ($path == 'combined_inbox') {
42: $list_path = 'combined_inbox';
43: $message_list_since = $handler->user_config->get('all_since_setting', DEFAULT_ALL_SINCE);
44: $per_source_limit = $handler->user_config->get('all_per_source_setting', DEFAULT_ALL_PER_SOURCE);
45: $mailbox_list_title = array('Everything');
46: }
47: elseif ($path == 'junk') {
48: $list_path = 'junk';
49: $message_list_since = $handler->user_config->get('junk_since_setting', DEFAULT_JUNK_SINCE);
50: $per_source_limit = $handler->user_config->get('junk_per_source_setting', DEFAULT_JUNK_PER_SOURCE);
51: $mailbox_list_title = array('Junk');
52: }
53: elseif ($path == 'snoozed') {
54: $list_path = 'snoozed';
55: $message_list_since = $handler->user_config->get('snoozed_since_setting', DEFAULT_SNOOZED_SINCE);
56: $per_source_limit = $handler->user_config->get('snoozed_per_source_setting', DEFAULT_SNOOZED_PER_SOURCE);
57: $mailbox_list_title = array('Snoozed');
58: }
59: elseif ($path == 'trash') {
60: $list_path = 'trash';
61: $message_list_since = $handler->user_config->get('trash_since_setting', DEFAULT_TRASH_SINCE);
62: $per_source_limit = $handler->user_config->get('trash_per_source_setting', DEFAULT_TRASH_PER_SOURCE);
63: $mailbox_list_title = array('Trash');
64: }
65: elseif ($path == 'sent') {
66: $list_path = 'sent';
67: $message_list_since = $handler->user_config->get('sent_since_setting', DEFAULT_SENT_SINCE);
68: $per_source_limit = $handler->user_config->get('sent_per_source_setting', DEFAULT_SENT_PER_SOURCE);
69: $mailbox_list_title = array('Sent');
70: }
71: elseif ($path == 'drafts') {
72: $list_path = 'drafts';
73: $message_list_since = $handler->user_config->get('drafts_since_setting', DEFAULT_DRAFT_SINCE);
74: $per_source_limit = $handler->user_config->get('drafts_per_source_setting', DEFAULT_DRAFT_PER_SOURCE);
75: $mailbox_list_title = array('Drafts');
76: }
77: elseif ($path == 'tag' && $handler->module_is_supported('tags')) {
78: $list_path = 'tag';
79: $message_list_since = $handler->user_config->get('tag_since_setting', DEFAULT_TAGS_SINCE);
80: $per_source_limit = $handler->user_config->get('tag_per_source_setting', DEFAULT_TAGS_PER_SOURCE);
81: $mailbox_list_title = array('Tag');
82: }
83: return array($list_path, $mailbox_list_title, $message_list_since, $per_source_limit);
84: }}
85:
86: /**
87: * Build meta information for a message list
88: * @subpackage core/functions
89: * @param array $input module output
90: * @param object $output_mod Hm_Output_Module
91: * @return string
92: */
93: if (!hm_exists('message_list_meta')) {
94: function message_list_meta($input, $output_mod) {
95: if (!array_key_exists('list_meta', $input) || !$input['list_meta']) {
96: return '';
97: }
98: $limit = 0;
99: $since = false;
100: $times = array(
101: 'today' => 'Today',
102: '-1 week' => 'Last 7 days',
103: '-2 weeks' => 'Last 2 weeks',
104: '-4 weeks' => 'Last 4 weeks',
105: '-6 weeks' => 'Last 6 weeks',
106: '-6 months' => 'Last 6 months',
107: '-1 year' => 'Last year',
108: '-5 years' => 'Last 5 years'
109: );
110: if (array_key_exists('per_source_limit', $input)) {
111: $limit = $input['per_source_limit'];
112: }
113: if (!$limit) {
114: $limit = DEFAULT_PER_SOURCE;
115: }
116: if (array_key_exists('message_list_since', $input)) {
117: $since = $input['message_list_since'];
118: }
119: if (!$since) {
120: $since = DEFAULT_SINCE;
121: }
122: $date = sprintf('%s', mb_strtolower($output_mod->trans($times[$since])));
123: $max = sprintf($output_mod->trans('%d items per source'), $limit);
124: $sources = '<span class="src_count">0</span>&nbsp;' . $output_mod->trans('sources');
125: $total = '<span class="total">0</span>&nbsp;' .$output_mod->trans('total');
126:
127: return '<div class="list_meta d-flex align-items-center fs-6 text-nowrap me-auto mb-2 mb-md-0">'.$date.':&nbsp;'.$sources.',&nbsp;'.$max.',&nbsp;'.$total.'</div>';
128: }}
129:
130: /**
131: * Build sort dialog for a combined list
132: * @subpackage core/functions
133: * @param object $output_mod Hm_Output_Module
134: * @return string
135: */
136: if (!hm_exists('combined_sort_dialog')) {
137: function combined_sort_dialog($mod) {
138: $sorts = [
139: 'arrival' => $mod->trans('Arrival Date'),
140: 'date' => $mod->trans('Sent Date'),
141: 'from' => $mod->trans('From'),
142: 'to' => $mod->trans('To'),
143: 'subject' => $mod->trans('Subject')
144: ];
145:
146: $res = '<select name="sort" style="width: 150px" class="combined_sort form-select form-select-sm ms-2">';
147: foreach ($sorts as $name => $val) {
148: $res .= '<option value="'.$name.'"'.($mod->get('list_sort') == $name ? ' selected' : '').'>'.$val.' &darr;</option>';
149: $res .= '<option value="-'.$name.'"'.($mod->get('list_sort') == '-'.$name ? ' selected' : '').'>'.$val.' &uarr;</option>';
150: }
151: $res .= '</select>';
152: return $res;
153: }}
154:
155: /**
156: * Build a human readable interval string
157: * @subpackage core/functions
158: * @param string $date_str date string parsable by strtotime()
159: * @return string
160: */
161: if (!hm_exists('human_readable_interval')) {
162: function human_readable_interval($date_str) {
163: if (!$date_str) {
164: return 'Unknown';
165: }
166: $precision = 2;
167: $interval_time = array();
168: $date = strtotime($date_str);
169: $interval = time() - $date;
170: $res = array();
171:
172: $t['second'] = 1;
173: $t['minute'] = $t['second']*60;
174: $t['hour'] = $t['minute']*60;
175: $t['day'] = $t['hour']*24;
176: $t['week'] = $t['day']*7;
177: $t['month'] = $t['day']*30;
178: $t['year'] = $t['week']*52;
179:
180: if ($interval < -300) {
181: return 'From the future!';
182: }
183: elseif ($interval <= 0) {
184: return 'Just now';
185: }
186: foreach (array_reverse($t) as $name => $val) {
187: if ($interval_time[$name] = ($interval/$val > 0) ? floor($interval/$val) : false) {
188: $interval -= $val*$interval_time[$name];
189: }
190: }
191: $interval_time = array_slice(array_filter($interval_time, function($v) { return $v > 0; }), 0, $precision);
192: foreach($interval_time as $name => $val) {
193: if ($val > 1) {
194: $res[] = sprintf('%d %ss', $val, $name);
195: }
196: else {
197: $res[] = sprintf('%d %s', $val, $name);
198: }
199: }
200: return implode(', ', $res);
201: }}
202:
203: /**
204: * Output a message list row of data using callbacks
205: * @subpackage core/functions
206: * @param array $values data and callbacks for each cell
207: * @param string $id unique id for the message
208: * @param string $style message list style (news or email)
209: * @param object $output_mod Hm_Output_Module
210: * @param string $row_class optional table row css class
211: * @return array
212: */
213: if (!hm_exists('message_list_row')) {
214: function message_list_row($values, $id, $style, $output_mod, $row_class='', $msgId = '', $inReplyTo = '') {
215: $res = '<tr class="'.$output_mod->html_safe($id);
216: if ($row_class) {
217: $res .= ' '.$output_mod->html_safe($row_class);
218: }
219: if (!empty($msgId)) {
220: $res .= '" data-msg-id="'.$output_mod->html_safe($msgId);
221: }
222: if (!empty($inReplyTo)) {
223: $res .= '" data-in-reply-to="'.$output_mod->html_safe($inReplyTo);
224: }
225: $data_uid = "";
226: if ($uids = explode("_", $id)) {
227: if (isset($uids[2])) {
228: $data_uid = 'data-uid="'. $uids[2] .'"';
229: }
230: }
231: if (!empty($data_uid)) {
232: $res .= '" '.$data_uid.'>';
233: } else {
234: $res .= '">';
235: }
236:
237: if ($style == 'news') {
238: $res .= '<td class="news_cell checkbox_cell">';
239: }
240: foreach ($values as $vals) {
241: if (function_exists($vals[0])) {
242: $function = array_shift($vals);
243: $res .= $function($vals, $style, $output_mod);
244: }
245: }
246: if ($style == 'news') {
247: $res .= '</td>';
248: }
249: $res .= '</tr>';
250: return array($res, $id);
251: }}
252:
253: /**
254: * Generic callback for a message list table cell
255: * @subpackage core/functions
256: * @param array $vals data for the cell
257: * @param string $style message list style
258: * @param object $output_mod Hm_Output_Module
259: * @return string
260: */
261: if (!hm_exists('safe_output_callback')) {
262: function safe_output_callback($vals, $style, $output_mod) {
263: $img = '';
264: $title = '';
265: if (count($vals) > 2) {
266: if ($vals[2]){
267: $img = '<i class="bi bi-filetype-'.$vals[2].'"></i>';
268: }
269: if (count($vals) > 3) {
270: $title = $output_mod->html_safe($vals[3]);
271: } else {
272: $title = $output_mod->html_safe($vals[1]);
273: }
274: }
275: if ($style == 'news') {
276: return sprintf('<div class="%s" data-title="%s">%s%s</div>', $output_mod->html_safe($vals[0]), $title, $img, $output_mod->html_safe($vals[1]));
277: }
278: return sprintf('<td class="%s" data-title="%s">%s%s</td>', $output_mod->html_safe($vals[0]), $title, $img, $output_mod->html_safe($vals[1]));
279: }}
280:
281: /**
282: * Callback for a message list checkbox
283: * @subpackage core/functions
284: * @param array $vals data for the cell
285: * @param string $style message list style
286: * @param object $output_mod Hm_Output_Module
287: * @return string
288: */
289: if (!hm_exists('checkbox_callback')) {
290: function checkbox_callback($vals, $style, $output_mod) {
291: if ($style == 'news') {
292: return sprintf('<input type="checkbox" id="%s" value="%s" />'.
293: '<label class="checkbox_label" for="%s"></label>'.
294: '</td><td class="news_cell">', $output_mod->html_safe($vals[0]),
295: $output_mod->html_safe($vals[0]), $output_mod->html_safe($vals[0]));
296: }
297: return sprintf('<td class="checkbox_cell">'.
298: '<input id="'.$output_mod->html_safe($vals[0]).'" type="checkbox" value="%s" />'.
299: '<label class="checkbox_label" for="'.$output_mod->html_safe($vals[0]).'"></label>'.
300: '</td>', $output_mod->html_safe($vals[0]));
301: }}
302:
303: /**
304: * Callback for a subject cell in a message list
305: * @subpackage core/functions
306: * @param array $vals data for the cell
307: * @param string $style message list style
308: * @param object $output_mod Hm_Output_Module
309: * @return string
310: */
311: if (!hm_exists('subject_callback')) {
312: function subject_callback($vals, $style, $output_mod) {
313: $img = '';
314: $subject = '';
315: $preview_msg = '';
316: if (isset($vals[3]) && $vals[3]) {
317: $img = '<i class="bi bi-filetype-'.$vals[3].'"></i>';
318: }
319: $subject = $output_mod->html_safe($vals[0]);
320: if (isset($vals[4]) && $vals[4]) {
321: $lines = explode("\n", $vals[4]);
322: $clean = array_filter(array_map('trim', $lines), function ($line) {
323: return $line !== ''
324: && stripos($line, 'boundary=') === false
325: && !preg_match('/^-{2,}==/', $line)
326: && stripos($line, 'content-type:') !== 0
327: && stripos($line, 'charset=') === false
328: && stripos($line, 'content-transfer-encoding:') !== 0;
329: });
330: $clean_text = implode("\n", $clean);
331: $preview_msg = $output_mod->html_safe($clean_text);
332: }
333:
334: $hl_subject = preg_replace("/^(\[[^\]]+\])/", '<span class="s_pre">$1</span>', $subject);
335: if ($style == 'news') {
336: if ($output_mod->get('is_mobile')) {
337: return sprintf('<div class="subject"><div class="%s" title="%s">%s <a href="%s">%s</a></div></div>', $output_mod->html_safe(implode(' ', $vals[2])), $subject, $img, $output_mod->html_safe($vals[1]), $hl_subject);
338: }
339: return sprintf('<div class="subject"><div class="%s" title="%s">%s <a href="%s">%s</a><p class="fw-light">%s</p></div></div>', $output_mod->html_safe(implode(' ', $vals[2])), $subject, $img, $output_mod->html_safe($vals[1]), $hl_subject, $preview_msg);
340: }
341:
342: if ($output_mod->get('is_mobile')) {
343: return sprintf('<td class="subject"><div class="%s"><a title="%s" href="%s">%s</a></div></td>', $output_mod->html_safe(implode(' ', $vals[2])), $subject, $output_mod->html_safe($vals[1]), $hl_subject);
344: }
345: return sprintf('<td class="subject"><div class="%s"><a title="%s" href="%s">%s</a><p class="fw-light">%s</p></div></td>', $output_mod->html_safe(implode(' ', $vals[2])), $subject, $output_mod->html_safe($vals[1]), $hl_subject, $preview_msg);
346: }}
347:
348: /**
349: * Callback for a date cell in a message list
350: * @subpackage core/functions
351: * @param array $vals data for the cell
352: * @param string $style message list style
353: * @param object $output_mod Hm_Output_Module
354: * @return string
355: */
356: if (!hm_exists('date_callback')) {
357: function date_callback($vals, $style, $output_mod) {
358: $delayed_class = isset($vals[2]) && $vals[2]? ' delayed_date': '';
359: if ($style == 'news') {
360: return sprintf('<div class="msg_date%s">%s<input type="hidden" class="msg_timestamp" value="%s" /></div>', $delayed_class, $output_mod->html_safe($vals[0]), $output_mod->html_safe($vals[1]));
361: }
362: return sprintf('<td class="msg_date%s" title="%s">%s<input type="hidden" class="msg_timestamp" value="%s" /></td>', $delayed_class, $output_mod->html_safe(date('r', $vals[1])), $output_mod->html_safe($vals[0]), $output_mod->html_safe($vals[1]));
363: }}
364:
365: function dates_holders_callback($vals) {
366: $res = '<td class="dates d-none">';
367: $res .= '<input type="hidden" name="arrival" class="arrival" value="'. $vals[0] .'" arial-label="Arrival date" />';
368: $res .= '<input type="hidden" name="date" class="date" value="'. $vals[1] .'" arial-label="Sent date" />';
369: $res .= '</td>';
370: return $res;
371: }
372:
373: /**
374: * Callback for an icon in a message list row
375: * @subpackage core/functions
376: * @param array $vals data for the cell
377: * @param string $style message list style
378: * @param object $output_mod Hm_Output_Module
379: * @return string
380: */
381: if (!hm_exists('icon_callback')) {
382: function icon_callback($vals, $style, $output_mod) {
383: $icons = '';
384: $title = array();
385: $show_icons = $output_mod->get('msg_list_icons');
386: if (in_array('flagged', $vals[0])) {
387: $icons .= $show_icons ? '<i class="bi bi-star-half"></i>' : ' F';
388: $title[] = $output_mod->trans('Flagged');
389: }
390: if (in_array('draft', $vals[0])) {
391: $icons .= $show_icons ? '<i class="bi bi-star-half"></i>' : ' D';
392: $title[] = $output_mod->trans('Draft');
393: }
394: if (in_array('answered', $vals[0])) {
395: $icons .= $show_icons ? '<i class="bi bi-check-circle-fill"></i>' : ' A';
396: $title[] = $output_mod->trans('Answered');
397: }
398: if (in_array('attachment', $vals[0])) {
399: $icons .= $show_icons ? '<i class="bi bi-paperclip"></i>' : ' <i class="bi bi-plus-circle"></i>';
400: $title[] = $output_mod->trans('Attachment');
401: }
402: $title = implode(', ', $title);
403: if ($style == 'news') {
404: return sprintf('<div class="icon" title="%s">%s</div>', $title, $icons);
405: }
406: return sprintf('<td class="icon" title="%s">%s</td>', $title, $icons);
407: }}
408:
409: /**
410: * Output message controls
411: * @subpackage core/functions
412: * @param object $output_mod Hm_Output_Module
413: * @return string
414: */
415: if (!hm_exists('message_controls')) {
416: function message_controls($output_mod) {
417: $txt = '';
418: $controls = ['read', 'unread', 'flag', 'unflag', 'delete', 'archive', 'junk'];
419: $controls = array_filter($controls, function($val) use ($output_mod) {
420: if (in_array($val, [$output_mod->get('list_path', ''), strtolower($output_mod->get('core_msg_control_folder', ''))])) {
421: return false;
422: }
423: if ($val == 'flag' && $output_mod->get('list_path', '') == 'flagged') {
424: return false;
425: }
426: return true;
427: });
428:
429: $res = '<a class="toggle_link" href="#"><i class="bi bi-check-square-fill"></i></a>'.
430: '<div class="msg_controls fs-6 d-none gap-1 align-items-center">'.
431: '<div class="dropdown on_mobile">'.
432: '<button type="button" class="btn btn-outline-secondary btn-sm dropdown-toggle" id="coreMsgControlDropdown" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="true">Actions</button>'.
433: '<ul class="dropdown-menu" aria-labelledby="coreMsgControlDropdown">';
434: foreach ($controls as $control) {
435: $res .= '<li><a class="dropdown-item msg_'.$control.' core_msg_control btn btn-sm btn-light text-black-50" href="#" data-action="'.$control.'">'.$output_mod->trans(ucfirst($control)).'</a></li>';
436: }
437: $res .= '</ul>'.
438: '</div>';
439:
440: foreach ($controls as $control) {
441: $res .= '<a class="msg_'.$control.' core_msg_control btn btn-sm btn-light no_mobile border text-black-50" href="#" data-action="'.$control.'">'.$output_mod->trans(ucfirst($control)).'</a>';
442: }
443:
444: if ($output_mod->get('msg_controls_extra')) {
445: $res .= $output_mod->get('msg_controls_extra');
446: }
447: if(!empty($output_mod->get('tags'))) {
448: $res .= tags_dropdown($output_mod, []);
449: }
450: $res .= '</div>';
451: return $res;
452: }}
453:
454: /**
455: * Output select element for "received since" options
456: * @subpackage core/functions
457: * @param string $since current value to pre-select
458: * @param string $name name used as the elements id and name
459: * @param object $output_mod Hm_Output_Module
460: * @return string
461: */
462: if (!hm_exists('message_since_dropdown')) {
463: function message_since_dropdown($since, $name, $output_mod, $original_default_value = '-1 week') {
464: $times = array(
465: 'today' => 'Today',
466: '-1 week' => 'Last 7 days',
467: '-2 weeks' => 'Last 2 weeks',
468: '-4 weeks' => 'Last 4 weeks',
469: '-6 weeks' => 'Last 6 weeks',
470: '-6 months' => 'Last 6 months',
471: '-1 year' => 'Last year',
472: '-5 years' => 'Last 5 years'
473: );
474: $res = '<select name="'.$name.'" id="'.$name.'" class="message_list_since form-select form-select-sm" data-default-value="'.$original_default_value.'">';
475: $reset = '';
476: foreach ($times as $val => $label) {
477: $res .= '<option';
478: if ($val == $since) {
479: $res .= ' selected="selected"';
480: if ($val != $original_default_value) {
481: $reset = '<span class="tooltip_restore" restore_aria_label="Restore default value"><i class="bi bi-arrow-counterclockwise refresh_list reset_default_value_select"></i></span>';
482: }
483:
484: }
485: $res .= ' value="'.$val.'">'.$output_mod->trans($label).'</option>';
486: }
487: $res .= '</select>'.$reset;
488: return $res;
489: }}
490:
491: /**
492: * Output a source list for a message list
493: * @subpackage core/functions
494: * @param array $sources source of the list
495: * @param object $output_mod Hm_Output_Module
496: */
497: if (!hm_exists('list_sources')) {
498: function list_sources($sources, $output_mod) {
499: $res = '<div class="list_sources w-100 mt-2">';
500: $res .= '<div class="src_title fs-5 mb-2">'.$output_mod->html_safe('Sources').'</div>';
501: foreach ($sources as $src) {
502: if (array_key_exists('group', $src) && $src['group'] == 'background') {
503: continue;
504: }
505: if (array_key_exists('nodisplay', $src) && $src['nodisplay']) {
506: continue;
507: }
508: if ($src['type'] == 'imap' && !array_key_exists('folder_name', $src)) {
509: $folder = 'INBOX';
510: }
511: elseif (!array_key_exists('folder_name', $src)) {
512: $folder = '';
513: }
514: else {
515: $folder = $src['folder_name'];
516: }
517: $res .= '<div class="list_src">'.$output_mod->html_safe($src['type']).' '.$output_mod->html_safe($src['name']);
518: $res .= ' '.$output_mod->html_safe($folder);
519: $res .= '</div>';
520: }
521: $res .= '</div>';
522: return $res;
523: }}
524:
525:
526:
527: /**
528: * Output a source list for a message list
529: * @subpackage core/functions
530: * @param array $sources source of the list
531: * @param object $output_mod Hm_Output_Module
532: */
533: if (!hm_exists('update_search_label_field')) {
534: function update_search_label_field($search_term, $output_mod) {
535: $res = '<div class="update_search_label_field">';
536: $res .= '<div class="update_saved_search_title">'.$output_mod->html_safe('Update saved search label') .'</div>';
537: $res .= '<div>
538: <input type="hidden" name="page" value="search">
539: <input type="hidden" name="search_terms" value="'. $search_term .'">
540: <label class="screen_reader" for="search_terms_label">Current Search Label</label>
541: <input required="" disabled id="old_search_terms_label" type="search" value="' . $search_term . '" class="old_search_terms_label form-control form-control-sm" name="old_search_terms_label">
542: <label class="screen_reader" for="search_terms_label">New Search Terms</label>
543: <input required="" placeholder="New search terms label" id="search_terms_label" type="search" class="search_terms_label form-control form-control-sm" name="search_terms_label">
544: <div>
545: <input type="button" class="search_label_update btn w-100 btn-primary btn-sm" value="Update">
546: </div>
547: </div>';
548: $res .= '</div>';
549: return $res;
550: }}
551:
552:
553:
554:
555:
556:
557:
558:
559:
560:
561:
562:
563:
564:
565:
566:
567:
568:
569:
570: /**
571: * Output message list controls
572: * @subpackage core/functions
573: * @param string $refresh_link refresh link tag
574: * @param string $config_link configuration link tag
575: * @param string $source_link source link tag
576: * @return string
577: */
578: if (!hm_exists('list_controls')) {
579: function list_controls($refresh_link, $config_link, $source_link = false, $search_field = '') {
580: return '<div class="list_controls no_mobile d-flex gap-3 align-items-center">' .
581: $refresh_link . $source_link . $config_link . $search_field .
582: '</div>' .
583: '<div class="list_controls on_mobile">' .
584: $search_field .
585: '<i class="bi bi-filter-circle" onclick="listControlsMenu()"></i>' .
586: '<div id="list_controls_menu" class="list_controls_menu">' .
587: $refresh_link . $source_link . $config_link .
588: '</div>' .
589: '</div>';
590: }}
591:
592: /**
593: * Validate search terms
594: * @subpackage core/functions
595: * @param string $terms search terms to validate
596: * @return string
597: */
598: if (!hm_exists('validate_search_terms')) {
599: function validate_search_terms($terms) {
600: $terms = trim(strip_tags($terms));
601: if (!$terms) {
602: $terms = '';
603: }
604: return $terms;
605: }}
606:
607: /**
608: * Validate the name of a search field
609: * @subpackage core/functions
610: * @param string $fld name to validate
611: * @return mixed
612: */
613: if (!hm_exists('validate_search_fld')) {
614: function validate_search_fld($fld) {
615: if (in_array($fld, array('TEXT', 'BODY', 'FROM', 'SUBJECT', 'TO', 'CC'))) {
616: return $fld;
617: }
618: return false;
619: }}
620:
621: /**
622: * Output a select element for the search field
623: * @subpackage core/functions
624: * @param string $current currently selected field
625: * @param object $output_mod Hm_Output_Module
626: * @return string
627: */
628: if (!hm_exists('search_field_selection')) {
629: function search_field_selection($current, $output_mod) {
630: $flds = array(
631: 'TEXT' => 'Entire message',
632: 'BODY' => 'Message body',
633: 'SUBJECT' => 'Subject',
634: 'FROM' => 'From',
635: 'TO' => 'To',
636: 'CC' => 'Cc',
637: );
638: $res = '<select class="form-select form-select-sm" id="search_fld" name="search_fld">';
639: foreach ($flds as $val => $name) {
640: $res .= '<option ';
641: if ($current == $val) {
642: $res .= 'selected="selected" ';
643: }
644: $res .= 'value="'.$val.'">'.$output_mod->trans($name).'</option>';
645: }
646: $res .= '</select>';
647: return $res;
648: }}
649: