1: <?php
2:
3: /**
4: * highlights module set
5: * @package modules
6: * @subpackage highlights
7: */
8:
9: if (!defined('DEBUG_MODE')) { die(); }
10:
11: /*
12: * @subpackage highlights/handler
13: */
14: class Hm_Handler_highlight_list_data extends Hm_Handler_Module {
15: public function process() {
16: $this->out('highlight_rules', $this->user_config->get('highlight_rules', array()));
17: $this->out('github_repos', $this->user_config->get('github_repos', array()));
18: }
19: }
20:
21: /*
22: * @subpackage highlights/handler
23: */
24: class Hm_Handler_highlight_page_data extends Hm_Handler_Module {
25: public function process() {
26:
27: $imap = false;
28: $feeds = false;
29: $github = false;
30:
31: $modules = $this->config->get_modules();
32:
33: if ($this->module_is_supported('imap')) {
34: $imap = Hm_IMAP_List::dump(false);
35: }
36: if ($this->module_is_supported('feeds')) {
37: $feeds = Hm_Feed_List::dump(false);
38: }
39: if ($this->module_is_supported('github')) {
40: $github = $this->user_config->get('github_repos', array());
41: }
42: $this->out('highlight_sources', array(
43: 'imap' => $imap,
44: 'feeds' => $feeds,
45: 'github' => $github
46: ));
47: $this->out('highlight_rules', $this->user_config->get('highlight_rules', array()));
48: }
49: }
50:
51: /*
52: * @subpackage highlights/handler
53: */
54: class Hm_Handler_highlight_process_form extends Hm_Handler_Module {
55: public function process() {
56: if (array_key_exists('rule_del_id', $this->request->post)) {
57: $rules = $this->user_config->get('highlight_rules', array());
58: unset($rules[$this->request->post['rule_del_id']]);
59: $rules = array_merge($rules);
60: $this->user_config->set('highlight_rules', $rules);
61: $this->session->record_unsaved('Highlight rule deleted');
62: Hm_Msgs::add('Hightlight rule deleted');
63: return;
64: }
65: list($success, $form) = $this->process_form(array('hl_source_type', 'hl_target', 'hl_color'));
66: if (!$success) {
67: return;
68: }
69: if (!in_array($form['hl_source_type'], array('imap', 'feeds', 'github'))) {
70: return;
71: }
72: if (!preg_match("/^#[0-9abcdef]{6}$/", mb_strtolower($form['hl_color']))) {
73: return;
74: }
75: foreach (array('hl_important', 'hl_imap_flags', 'hl_imap_sources', 'hl_feeds_sources', 'hl_github_sources') as $fld) {
76: if (array_key_exists($fld, $this->request->post) && $this->request->post[$fld]) {
77: $form[$fld] = $this->request->post[$fld];
78: }
79: }
80: if ($form['hl_source_type'] == 'github' &&
81: array_key_exists('hl_github_unseen', $this->request->post) &&
82: $this->request->post['hl_github_unseen']) {
83: $form['hl_imap_flags'] = array('unseen');
84: }
85: elseif ($form['hl_source_type'] == 'feeds' &&
86: array_key_exists('hl_feeds_unseen', $this->request->post) &&
87: $this->request->post['hl_feeds_unseen']) {
88: $form['hl_imap_flags'] = array('unseen');
89: }
90: switch ($form['hl_source_type']) {
91: case 'imap':
92: $new_rule = hl_imap_rule($form);
93: break;
94: case 'feeds':
95: $new_rule = hl_feeds_rule($form);
96: break;
97: case 'github':
98: $new_rule = hl_github_rule($form, $this);
99: break;
100: }
101: $rules = $this->user_config->get('highlight_rules', array());
102: $rules[] = $new_rule;
103: $this->user_config->set('highlight_rules', $rules);
104: $this->session->record_unsaved('Highlight rule created');
105: Hm_Msgs::add('Hightlight rule created');
106: }
107: }
108:
109: /*
110: * @subpackage highlights/output
111: */
112: class Hm_Output_highlight_css extends Hm_Output_Module {
113: protected function output() {
114: $css = array();
115: $repos = $this->get('github_repos', array());
116: $rules = $this->get('highlight_rules', array());
117: $defaults = array('imap' => '.email', 'feeds' => '.feeds', 'github' => '.github');
118: foreach ($rules as $rule) {
119: $ids = get_rule_ids($rule['sources'], $rule['type'], $repos);
120: if (!$ids) {
121: $ids = array($defaults[$rule['type']]);
122: }
123: if ($rule['types']) {
124: if (!$ids) {
125: foreach ($rule['types'] as $type) {
126: $ids[] = '.'.$type;
127: }
128: }
129: else {
130: $updated = array();
131: foreach ($ids as $id) {
132: foreach ($rule['types'] as $type) {
133: $updated[] = $id.'.'.$type;
134: }
135: }
136: $ids = $updated;
137: }
138: }
139: foreach ($ids as $id) {
140: $css[] = sprintf('.message_table %s td {%s: %s !important;}',
141: $id,
142: ($rule['target'] == 'text' ? 'color': 'background-color'),
143: $rule['color'], ($rule['important'] ? '!important' : '')
144: );
145: if ($rule['target'] == 'text') {
146: $css[] = sprintf('.message_table %s td a {color: %s !important;}',
147: $id, $rule['color'], ($rule['important'] ? '!important' : ''));
148: }
149: else {
150: $css[] = sprintf('.message_table %s td div {background-color: %s !important;}',
151: $id, $rule['color'], ($rule['important'] ? '!important' : ''));
152: }
153: }
154: }
155: $res = '<style type="text/css">'.implode(' ', $css).'</style>';
156: return $res;
157: }
158: }
159:
160: /*
161: * @subpackage highlights/output
162: */
163: class Hm_Output_highlight_config_page extends Hm_Output_Module {
164: protected function output() {
165: $rules = $this->get('highlight_rules', array());
166: $sources = $this->get('highlight_sources', array());
167: $source_types = array('E-mail' => 'imap');
168: if ($sources['feeds'] !== false) {
169: $source_types['RSS'] = 'feeds';
170: }
171: if ($sources['github'] !== false) {
172: $source_types['Github'] = 'github';
173: }
174: $email_types = array(
175: 'Unseen' => 'unseen',
176: 'Seen' => 'seen',
177: 'Flagged' => 'flagged',
178: 'Deleted' => 'deleted',
179: 'Anwered' => 'answered'
180: );
181: $targets = array(
182: 'Text' => 'text',
183: 'Background' => 'background'
184: );
185: $res = '<div class="content_title">'.$this->trans('Message highlighting').'</div>';
186: $res .= '<div class="settings_subtitle mt-3 mb-2"><b>'.$this->trans('Existing rules').'</b></div>';
187: if (!$rules) {
188: $res .= '<div class="empty_list">'.$this->trans('No rules').'</div>';
189: }
190: else {
191: $res .= '<div class="px-3"><table class="hl_rules table table-striped">'.
192: '<th>'.$this->trans('Type').'</th>'.
193: '<th>'.$this->trans('Target').'</th>'.
194: '<th>'.$this->trans('Color').'</th>'.
195: '<th>'.$this->trans('Sources').'</th>'.
196: '<th>'.$this->trans('Flags').'</th><th>'.$this->trans('Force').'</th><th></th></tr>';
197: foreach ($rules as $index => $rule) {
198: if ($rule['types']) {
199: $types = implode(' ', $rule['types']);
200: }
201: else {
202: $types = '*';
203: }
204: if ($rule['sources']) {
205: $src = array();
206: foreach ($rule['sources'] as $vals) {
207: $src[] = $vals['name'];
208: }
209: $src = implode(' ', $src);
210: }
211: else {
212: $src = '*';
213: }
214: $res .= '<tr>'.
215: '<td>'.$this->html_safe($rule['type']).'</td>'.
216: '<td>'.$this->html_safe($rule['target']).'</td>'.
217: '<td style="'.($rule['target'] == 'text' ? 'color' : 'background-color').': '.
218: $this->html_safe($rule['color']).' !important;">'.$this->html_safe($rule['color']).'</td>'.
219: '<td>'.$this->html_safe($src).'</td>'.
220: '<td>'.$this->html_safe($types).'</td>'.
221: '<td>'.$this->html_safe($rule['important'] ? 'true' : 'false').'</td>'.
222: '<td><form method="POST">'.
223: '<input type="hidden" name="hm_page_key" value="'.$this->html_safe(Hm_Request_Key::generate()).'" />'.
224: '<input type="hidden" name="rule_del_id" value="'.$this->html_safe($index).'" />'.
225: '<button type="submit" class="rule_del btn btn-light"><i class="bi bi-x-circle-fill"></i></button></form>'.
226: '</tr>';
227: }
228: }
229: $res .= '</table></div>';
230:
231: $res .= '<div class="settings_subtitle mt-3 px-3"><b>'.$this->trans('Add a new rule').'</b></div>';
232: $res .= '<div class="col-12 col-lg-5 mt-2 px-3">';
233: $res .= '<form method="POST">';
234:
235: // Source Type
236: $res .= '<div class="form-floating mb-3">';
237: $res .= '<select name="hl_source_type" required class="form-select hl_source_type">';
238: $res .= '<option selected="selected">'.$this->trans('Select source type').'</option>';
239: foreach ($source_types as $name => $val) {
240: $res .= '<option value="'.$this->html_safe($val).'">'.$this->trans($name).'</option>';
241: }
242: $res .= '</select>';
243: $res .= '<label>'.$this->trans('Source type').'</label></div>';
244:
245: // IMAP Flags
246: if ($sources['imap']) {
247: $res .= '<div class="form-floating mb-3 imap_row d-none">';
248: $res .= '<select style="min-height: 8rem" name="hl_imap_flags[]" size="4" multiple="multiple" class="form-select imap_flags">';
249: foreach ($email_types as $index => $value) {
250: $res .= '<option value="'.$this->html_safe($value).'">'.$this->trans($index).'</option>';
251: }
252: $res .= '</select>';
253: $res .= '<label>'.$this->trans('Flags').'</label></div>';
254:
255: // IMAP Accounts
256: $res .= '<div class="form-floating mb-3 imap_row d-none">';
257: $res .= '<select style="min-height: 8rem" name="hl_imap_sources[]" size="4" multiple="multiple" class="form-select imap_source">';
258: foreach ($sources['imap'] as $index => $vals) {
259: $res .= '<option value="'.$this->html_safe($index).'">'.$this->trans($vals['name']).'</option>';
260: }
261: $res .= '</select>';
262: $res .= '<label>'.$this->trans('Accounts').'</label></div>';
263: }
264:
265: // Feeds
266: if ($sources['feeds']) {
267: // Feeds Sources
268: $res .= '<div class="form-floating mb-3 feeds_row d-none">';
269: $res .= '<select style="min-height: 8rem" name="hl_feeds_sources[]" size="4" multiple="multiple" class="form-select feeds_source">';
270: foreach ($sources['feeds'] as $index => $vals) {
271: $res .= '<option value="'.$this->html_safe($index).'">'.$this->trans($vals['name']).'</option>';
272: }
273: $res .= '</select>';
274: $res .= '<label>'.$this->trans('Feeds').'</label></div>';
275:
276: // Unseen Feeds
277: $res .= '<div class="form-check mb-3 feeds_row d-none">';
278: $res .= '<input name="hl_feeds_unseen" type="checkbox" value="true" class="form-check-input" />';
279: $res .= '<label class="form-check-label">'.$this->trans('Unseen').'</label></div>';
280: }
281:
282: // GitHub
283: if ($sources['github']) {
284: // GitHub Repos
285: $res .= '<div class="form-floating mb-3 github_row d-none">';
286: $res .= '<select style="min-height: 8rem" name="hl_github_sources[]" size="4" multiple="multiple" class="form-select github_source">';
287: foreach ($sources['github'] as $repo) {
288: $res .= '<option value="'.$this->html_safe($repo).'">'.$this->trans($repo).'</option>';
289: }
290: $res .= '</select>';
291: $res .= '<label>'.$this->trans('Repos').'</label></div>';
292:
293: // Unseen GitHub
294: $res .= '<div class="form-check mb-3 github_row d-none">';
295: $res .= '<input name="hl_github_unseen" type="checkbox" value="true" class="form-check-input" />';
296: $res .= '<label class="form-check-label">'.$this->trans('Unseen').'</label></div>';
297: }
298:
299: // Highlight Target
300: $res .= '<div class="form-floating mb-3">';
301: $res .= '<select name="hl_target" class="form-select">';
302: foreach ($targets as $name => $val) {
303: $res .= '<option value="'.$this->html_safe($val).'">'.$this->trans($name).'</option>';
304: }
305: $res .= '</select>';
306: $res .= '<label>'.$this->trans('Highlight target').'</label></div>';
307:
308: // Highlight Color
309: $res .= '<div class="mb-3">';
310: $res .= '<label>'.$this->trans('Highlight color').'</label>';
311: $res .= '<input style="min-height: 3rem" name="hl_color" type="color" class="form-control p-1" /></div>';
312:
313: // CSS Override
314: $res .= '<div class="form-check mb-3">';
315: $res .= '<input value="true" type="checkbox" name="hl_important" class="form-check-input" />';
316: $res .= '<label class="form-check-label">'.$this->trans('CSS override').'</label></div>';
317:
318: // Submit Button
319: $res .= '<div class="submit_row">';
320: $res .= '<input type="submit" value="'.$this->trans('Add').'" class="btn btn-primary px-5" />';
321: $res .= '<input type="hidden" name="hm_page_key" value="'.$this->html_safe(Hm_Request_Key::generate()).'" />';
322: $res .= '</div></form></div>';
323:
324: return $res;
325:
326: }
327: }
328:
329: /*
330: * @subpackage highlights/output
331: */
332: class Hm_Output_highlight_link extends Hm_Output_Module {
333: protected function output() {
334: $res = '<li class="menu_highlights"><a class="unread_link" href="?page=highlights">';
335: if (!$this->get('hide_folder_icons')) {
336: $res .= '<i class="bi bi-highlighter fs-5 me-2"></i>';
337: }
338: $res .= $this->trans('Highlights').'</a></li>';
339: if ($this->format == 'HTML5') {
340: return $res;
341: }
342: $this->concat('formatted_folder_list', $res);
343: }
344: }
345:
346: /*
347: * @subpackage highlights/functions
348: */
349: function hl_base_rule($form, $type) {
350: if (array_key_exists('hl_important', $form) && $form['hl_important']) {
351: $important = true;
352: }
353: else {
354: $important = false;
355: }
356: return array(
357: 'important' => $important,
358: 'type' => $type,
359: 'color' => $form['hl_color'],
360: 'target' => $form['hl_target'],
361: 'sources' => array(),
362: 'types' => array()
363: );
364: }
365:
366: /*
367: * @subpackage highlights/functions
368: */
369: function hl_imap_rule($form) {
370: $rule = hl_base_rule($form, 'imap');
371: if (array_key_exists('hl_imap_sources', $form)) {
372: foreach ($form['hl_imap_sources'] as $id) {
373: $server = Hm_IMAP_List::dump($id);
374: if (!$server) {
375: continue;
376: }
377: $rule['sources'][] = array('name' => $server['name'],
378: 'user' => $server['user'], 'server' => $server['server']);
379: }
380: }
381: if (array_key_exists('hl_imap_flags', $form)) {
382: $rule['types'] = $form['hl_imap_flags'];
383: }
384: return $rule;
385: }
386:
387: /*
388: * @subpackage highlights/functions
389: */
390: function hl_feeds_rule($form) {
391: $rule = hl_base_rule($form, 'feeds');
392: if (array_key_exists('hl_feeds_sources', $form)) {
393: foreach ($form['hl_feeds_sources'] as $id) {
394: $server = Hm_Feed_List::dump($id);
395: if (!$server) {
396: continue;
397: }
398: $rule['sources'][] = array('server' => $server['server'],
399: 'name' => $server['name']);
400: }
401: }
402: if (array_key_exists('hl_imap_flags', $form)) {
403: $rule['types'] = $form['hl_imap_flags'];
404: }
405: return $rule;
406: }
407:
408: /*
409: * @subpackage highlights/functions
410: */
411: function hl_github_rule($form, $mod) {
412: $rule = hl_base_rule($form, 'github');
413: if (array_key_exists('hl_github_sources', $form)) {
414: $repos = $mod->user_config->get('github_repos', array());
415: foreach ($form['hl_github_sources'] as $id) {
416: foreach ($repos as $repo) {
417: if ($id == $repo) {
418: $rule['sources'][] = array('server' => $repo, 'name' => $repo);
419: }
420: }
421: }
422: }
423: if (array_key_exists('hl_imap_flags', $form)) {
424: $rule['types'] = $form['hl_imap_flags'];
425: }
426: return $rule;
427: }
428:
429: /*
430: * @subpackage highlights/functions
431: */
432: function get_rule_ids($sources, $type, $repos) {
433: if ($type == 'imap') {
434: return get_imap_ids($sources);
435: }
436: elseif ($type == 'feeds') {
437: return get_feed_ids($sources);
438: }
439: elseif ($type == 'github') {
440: return get_github_ids($sources, $repos);
441: }
442: else {
443: return array();
444: }
445: }
446:
447: /*
448: * @subpackage highlights/functions
449: */
450: function get_imap_ids($sources) {
451: $ids = array();
452: foreach (Hm_IMAP_List::dump() as $index => $vals) {
453: foreach ($sources as $src) {
454: if ($src['user'] == $vals['user'] && $src['server'] == $vals['server']) {
455: $ids[] = sprintf('[class^="imap_%s_"]', $index);
456: }
457: }
458: }
459: return $ids;
460: }
461:
462: /*
463: * @subpackage highlights/functions
464: */
465: function get_feed_ids($sources) {
466: $ids = array();
467: foreach (Hm_Feed_List::dump() as $index => $vals) {
468: foreach ($sources as $src) {
469: if ($src['name'] == $vals['name'] && $src['server'] == $vals['server']) {
470: $ids[] = sprintf('[class^="feeds_%s_"]', $index);
471: }
472: }
473: }
474: return $ids;
475: }
476:
477: /*
478: * @subpackage highlights/functions
479: */
480: function get_github_ids($sources, $repos) {
481: $ids = array();
482: foreach ($repos as $index => $val) {
483: foreach ($sources as $src) {
484: if ($src['server'] == $val) {
485: $ids[] = sprintf('[class^="github_%s_"]', $index);
486: }
487: }
488: }
489: return $ids;
490: }
491: