Mercurial > hg > rc1
annotate plugins/advanced_search/advanced_search.php @ 47:121a341ecb84
use the systemwide source
| author | Charlie Root |
|---|---|
| date | Thu, 28 Aug 2025 10:59:24 -0400 |
| parents | c822d3ec1f93 |
| children | 91f005a4f7e9 |
| rev | line source |
|---|---|
| 34 | 1 <?php |
| 2 /** | |
| 3 * Processing an advanced search over an E-Mail Account | |
| 4 * | |
| 5 * @version 2.1.5 | |
| 6 * @licence GNU GPLv3+ | |
| 7 * @author Wilwert Claude | |
| 8 * @author Ludovicy Steve | |
| 9 * @author Chris Moules | |
| 10 * @website http://www.gms.lu | |
| 11 * | |
| 12 * Updated by Alex S Grebenschikov (www.poralix.com) | |
| 13 * to make it compatible with RoundCube 1.3.0 | |
| 14 * Last modified: Tue Aug 1 06:41:46 CEST 2017 | |
| 15 * | |
| 16 */ | |
| 17 | |
| 18 class advanced_search extends rcube_plugin | |
| 19 { | |
| 20 | |
| 21 /** | |
| 22 * Instance of rcmail | |
| 23 * | |
| 24 * @var object | |
| 25 * @access private | |
| 26 */ | |
| 27 private $rc; | |
| 28 | |
| 29 public $task = 'mail|settings'; | |
| 30 | |
| 31 /** | |
| 32 * Plugin config | |
| 33 * | |
| 34 * @var array | |
| 35 * @access private | |
| 36 */ | |
| 37 private $config; | |
| 38 | |
| 39 /** | |
| 40 * Localization strings | |
| 41 * | |
| 42 * @var array | |
| 43 * @access private | |
| 44 */ | |
| 45 private $i18n_strings = array(); | |
| 46 | |
| 47 /** | |
| 48 * Initialisation of the plugin | |
| 49 * | |
| 50 * @access public | |
| 51 * @return null | |
| 52 */ | |
| 53 public function init() | |
| 54 { | |
| 55 $this->rc = rcmail::get_instance(); | |
| 56 $this->load_config("config-default.inc.php"); | |
| 57 $this->load_config(); | |
| 58 $this->config = $this->rc->config->get('advanced_search_plugin'); | |
| 59 $this->register_action('plugin.display_advanced_search', array($this, 'display_advanced_search')); | |
| 60 $this->register_action('plugin.trigger_search', array($this, 'trigger_search')); | |
| 61 $this->register_action('plugin.trigger_search_pagination', array($this, 'trigger_search_pagination')); | |
| 62 $this->register_action('plugin.save_search', array($this, 'save_search')); | |
| 63 $this->register_action('plugin.delete_search', array($this, 'delete_search')); | |
| 64 $this->register_action('plugin.get_saved_search', array($this, 'get_saved_search')); | |
| 65 | |
| 66 $this->skin = $this->rc->config->get('skin'); | |
| 67 $this->add_texts('localization', true); | |
| 68 $this->populate_i18n(); | |
| 69 if(isset($this->config['criteria'])) { | |
| 70 foreach($this->config['criteria'] as $key => $translation) { | |
| 71 $this->config['criteria'][$key] = $this->gettext($key); | |
| 72 } | |
| 73 } | |
| 74 $this->include_script('advanced_search.js'); | |
| 75 | |
| 76 if ($this->rc->task == 'mail') { | |
| 77 $file = 'skins/' . $this->skin . '/advanced_search.css'; | |
| 78 | |
| 79 if (file_exists($this->home . '/' . $file)) { | |
| 80 $this->include_stylesheet($file); | |
| 81 } else { | |
| 82 $this->include_stylesheet('skins/default/advanced_search.css'); | |
| 83 } | |
| 84 | |
| 85 if (empty($this->rc->action)) { | |
| 86 $this->add_menu_entry(); | |
| 87 } | |
| 88 } elseif ($this->rc->task == 'settings') { | |
| 89 $this->add_hook('preferences_list', array($this, 'preferences_list')); | |
| 90 $this->add_hook('preferences_save', array($this, 'preferences_save')); | |
| 91 $this->add_hook('preferences_sections_list', array($this, 'preferences_section')); | |
| 92 $file = 'skins/' . $this->skin . '/advanced_search.css'; | |
| 93 if (file_exists($this->home . '/' . $file)) { | |
| 94 $this->include_stylesheet($file); | |
| 95 } else { | |
| 96 $this->include_stylesheet('skins/default/advanced_search.css'); | |
| 97 } | |
| 98 } | |
| 99 | |
| 100 $this->add_hook('startup', array($this, 'startup')); | |
| 101 } | |
| 102 | |
| 103 | |
| 104 public function startup($args) | |
| 105 { | |
| 106 $search = rcube_utils::get_input_value('_search', rcube_utils::INPUT_GET); | |
| 107 if (!isset($search)) { | |
| 108 $search = rcube_utils::get_input_value('_search', rcube_utils::INPUT_POST); | |
| 109 } | |
| 110 $rsearch = $search == 'advanced_search_active'; | |
| 111 $uid = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_GET); | |
| 112 $draft_uid = rcube_utils::get_input_value('_draft_uid', rcube_utils::INPUT_GET); | |
| 113 $mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_GET); | |
| 114 $page = rcube_utils::get_input_value('_page', rcube_utils::INPUT_GET); | |
| 115 $sort = rcube_utils::get_input_value('_sort', rcube_utils::INPUT_GET); | |
| 116 | |
| 117 if (!empty($uid)) { | |
| 118 $parts = explode('__MB__', $uid); | |
| 119 if (count($parts) == 2) { | |
| 120 $search = 'advanced_search_active'; | |
| 121 } | |
| 122 } | |
| 123 if (!empty($draft_uid)) { | |
| 124 $parts = explode('__MB__', $draft_uid); | |
| 125 if (count($parts) == 2) { | |
| 126 $search = 'advanced_search_active'; | |
| 127 } | |
| 128 } | |
| 129 | |
| 130 if ($search == 'advanced_search_active') { | |
| 131 if ($args['action'] == 'show' && !empty($uid)) { | |
| 132 $parts = explode('__MB__', $uid); | |
| 133 $uid = $parts[0]; | |
| 134 $this->rc->output->redirect(array('_task' => 'mail', '_action' => $args['action'], '_mbox' => $mbox, '_uid' => $uid)); | |
| 135 } | |
| 136 if ($args['action'] == 'compose') { | |
| 137 $draft_uid = rcube_utils::get_input_value('_draft_uid', rcube_utils::INPUT_GET); | |
| 138 $parts = explode('__MB__', $draft_uid); | |
| 139 $draft_uid = $parts[0]; | |
| 140 if (!empty($draft_uid)) { | |
| 141 $this->rc->output->redirect(array('_task' => 'mail', '_action' => $args['action'], '_mbox' => $mbox, '_draft_uid' => $draft_uid)); | |
| 142 } | |
| 143 } | |
| 144 if ($args['action'] == 'list' && $rsearch) { | |
| 145 $this->rc->output->command('advanced_search_active', '_page=' . $page . '&_sort=' . $sort); | |
| 146 $this->rc->output->send(); | |
| 147 $args['abort'] = true; | |
| 148 } | |
| 149 if ($args['action'] == 'mark') { | |
| 150 $flag = rcube_utils::get_input_value('_flag', rcube_utils::INPUT_POST); | |
| 151 $uid = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_POST); | |
| 152 | |
| 153 $post_str = '_flag=' . $flag . '&_uid=' . $uid; | |
| 154 if ($quiet = rcube_utils::get_input_value('_quiet', rcube_utils::INPUT_POST)) { | |
| 155 $post_str .= '&_quiet=' . $quiet; | |
| 156 } | |
| 157 if ($from = rcube_utils::get_input_value('_from', rcube_utils::INPUT_POST)) { | |
| 158 $post_str .= '&_from=' . $from; | |
| 159 } | |
| 160 if ($count = rcube_utils::get_input_value('_count', rcube_utils::INPUT_POST)) { | |
| 161 $post_str .= '&_count=' . $count; | |
| 162 } | |
| 163 if ($ruid = rcube_utils::get_input_value('_ruid', rcube_utils::INPUT_POST)) { | |
| 164 $post_str .= '&_ruid=' . $ruid; | |
| 165 } | |
| 166 $this->rc->output->command('label_mark', $post_str); | |
| 167 $this->rc->output->send(); | |
| 168 $args['abort'] = true; | |
| 169 } | |
| 170 | |
| 171 } else { | |
| 172 if ($args['action'] != 'plugin.get_saved_search' && $args['action'] != 'plugin.save_search' && $args['action'] != 'plugin.delete_search') { | |
| 173 $this->rc->output->command('plugin.advanced_search_del_header', array()); | |
| 174 } | |
| 175 } | |
| 176 } | |
| 177 | |
| 178 /** | |
| 179 * This function populates an array with localization texts. | |
| 180 * This is needed as ew are using a lot of localizations from core. | |
| 181 * The core localizations are not avalable directly in JS | |
| 182 * | |
| 183 * @access private | |
| 184 * @return null | |
| 185 */ | |
| 186 private function populate_i18n() | |
| 187 { | |
| 188 $core = array('advsearch', 'search', 'resetsearch', 'addfield', 'delete', 'cancel'); | |
| 189 | |
| 190 foreach ($core as $label) { | |
| 191 $this->i18n_strings[$label] = $this->rc->gettext($label); | |
| 192 } | |
| 193 | |
| 194 $local = array('in', 'and', 'or', 'not', 'where', 'exclude', 'andsubfolders', 'allfolders', 'save_the_search', 'has_been_saved', 'deletesearch', 'has_been_deleted'); | |
| 195 | |
| 196 foreach ($local as $label) { | |
| 197 $this->i18n_strings[$label] = $this->gettext($label); | |
| 198 } | |
| 199 } | |
| 200 | |
| 201 /** | |
| 202 * This adds a button into the configured menu to use the advanced search | |
| 203 * | |
| 204 * @access public | |
| 205 * @return null | |
| 206 */ | |
| 207 public function add_menu_entry() | |
| 208 { | |
| 209 $displayOptions = $this->rc->config->get('advanced_search_display_options', array()); | |
| 210 $target_menu = (isset($displayOptions['target_menu']) && !empty($displayOptions['target_menu'])) ? $displayOptions['target_menu'] : $this->config['target_menu']; | |
| 211 if ($target_menu != 'toolbar') { | |
| 212 $this->api->add_content( | |
| 213 html::tag( | |
| 214 'li', | |
| 215 null, | |
| 216 $this->api->output->button( | |
| 217 array( | |
| 218 'command' => 'plugin.advanced_search', | |
| 219 'label' => 'advsearch', | |
| 220 'type' => 'link', | |
| 221 'classact' => 'icon advanced-search active', | |
| 222 'class' => 'icon advanced-search', | |
| 223 'innerclass' => 'icon advanced-search' | |
| 224 ) | |
| 225 ) | |
| 226 ), | |
| 227 $target_menu | |
| 228 ); | |
| 229 } else { | |
| 230 $this->api->add_content( | |
| 231 $this->api->output->button( | |
| 232 array( | |
| 233 'command' => 'plugin.advanced_search', | |
| 234 'title' => 'advsearch', | |
| 235 'label' => 'search', | |
| 236 'type' => 'link', | |
| 237 'classact' => 'button advanced-search active', | |
| 238 'class' => 'button advanced-search', | |
| 239 'innerclass' => 'button advanced-search', | |
| 240 ) | |
| 241 ), | |
| 242 $target_menu | |
| 243 ); | |
| 244 } | |
| 245 } | |
| 246 | |
| 247 /** | |
| 248 * This function quotes some specific values based on their data type | |
| 249 * | |
| 250 * @param mixed $input The value to get quoted | |
| 251 * @access public | |
| 252 * @return The quoted value | |
| 253 */ | |
| 254 public function quote($value) | |
| 255 { | |
| 256 if (getType($value) == 'string') { | |
| 257 if (!preg_match('/"/', $value)) { | |
| 258 $value = preg_replace('/^"/', '', $value); | |
| 259 $value = preg_replace('/"$/', '', $value); | |
| 260 $value = preg_replace('/"/', '\\"', $value); | |
| 261 } | |
| 262 | |
| 263 $value = '"' . $value . '"'; | |
| 264 } | |
| 265 | |
| 266 return $value; | |
| 267 } | |
| 268 | |
| 269 /** | |
| 270 * This function generates the IMAP compatible search query based on the request data (by javascript) | |
| 271 * | |
| 272 * @param array $input The raw criteria data sent by javascript | |
| 273 * @access private | |
| 274 * @return string or int | |
| 275 */ | |
| 276 private function process_search_part($search_part) | |
| 277 { | |
| 278 $command_str = ''; | |
| 279 $flag = false; | |
| 280 | |
| 281 // Check for valid input | |
| 282 if (!array_key_exists($search_part['filter'], $this->config['criteria'])) { | |
| 283 $this->rc->output->show_message($this->gettext('internalerror'), 'error'); | |
| 284 | |
| 285 return 0; | |
| 286 } | |
| 287 if (in_array($search_part['filter'], $this->config['flag_criteria'])) { | |
| 288 $flag = true; | |
| 289 } | |
| 290 if (!$flag && !(isset($search_part['filter-val']) && $search_part['filter-val'] != '')) { | |
| 291 return 1; | |
| 292 } | |
| 293 | |
| 294 // Negate part | |
| 295 if ($search_part['not'] == 'true') { | |
| 296 $command_str .= 'NOT '; | |
| 297 } | |
| 298 | |
| 299 $command_str .= $search_part['filter']; | |
| 300 | |
| 301 if (!$flag) { | |
| 302 if (in_array($search_part['filter'], $this->config['date_criteria'])) { | |
| 303 // Take date format from user environment | |
| 304 $date_format = $this->rc->config->get('date_format', 'Y-m-d'); | |
| 305 // Try to use PHP5.2+ DateTime but fallback to ugly old method | |
| 306 if (class_exists('DateTime')) { | |
| 307 $date = DateTime::createFromFormat($date_format, $search_part['filter-val']); | |
| 308 $command_str .= ' ' . $this->quote($date->format("d-M-Y")); | |
| 309 } else { | |
| 310 $date_format = preg_replace('/(\w)/', '%$1', $date_format); | |
| 311 $date_array = strptime($search_part['filter-val'], $date_format); | |
| 312 $unix_ts = mktime($date_array['tm_hour'], $date_array['tm_min'], $date_array['tm_sec'], $date_array['tm_mon']+1, $date_array['tm_mday'], $date_array['tm_year']+1900); | |
| 313 $command_str .= ' ' . $this->quote(date("d-M-Y", $unix_ts)); | |
| 314 } | |
| 315 } elseif (in_array($search_part['filter'], $this->config['email_criteria'])) { | |
| 316 // Strip possible ',' added by autocomplete | |
| 317 $command_str .= ' ' . $this->quote(trim($search_part['filter-val'], " \t,")); | |
| 318 } else { | |
| 319 // Don't try to use a value for a binary flag object | |
| 320 $command_str .= ' ' . $this->quote($search_part['filter-val']); | |
| 321 } | |
| 322 } | |
| 323 | |
| 324 return $command_str; | |
| 325 } | |
| 326 | |
| 327 /** | |
| 328 * This function generates the IMAP compatible search query based on the request data (by javascript) | |
| 329 * | |
| 330 * @param array $input The raw criteria data sent by javascript | |
| 331 * @access public | |
| 332 * @return The final search command | |
| 333 */ | |
| 334 public function get_search_query($input) | |
| 335 { | |
| 336 $command = array(); | |
| 337 | |
| 338 foreach ($input as $search_part) { | |
| 339 // Skip excluded parts | |
| 340 if ($search_part['excluded'] == 'true') { | |
| 341 continue; | |
| 342 } | |
| 343 if (! $part_command = $this->process_search_part($search_part)) { | |
| 344 return 0; | |
| 345 } | |
| 346 // Skip invalid parts | |
| 347 if ($part_command === 1) { | |
| 348 continue; | |
| 349 } | |
| 350 | |
| 351 $command[] = array('method' => isset($search_part['method']) ? $search_part['method'] : 'and', | |
| 352 'command' => $part_command); | |
| 353 } | |
| 354 | |
| 355 $command_string = $this->build_search_string($command); | |
| 356 | |
| 357 return $command_string; | |
| 358 } | |
| 359 | |
| 360 /** | |
| 361 * This function converts the preconfigured query parts (as array) into an IMAP compatible string | |
| 362 * | |
| 363 * @param array $command_array An array containing the advanced search criteria | |
| 364 * @access public | |
| 365 * @return The command string | |
| 366 */ | |
| 367 private function build_search_string($command_array) | |
| 368 { | |
| 369 $command = array(); | |
| 370 $paranthesis = 0; | |
| 371 $prev_method = null; | |
| 372 $next_method = null; | |
| 373 $cnt = count($command_array); | |
| 374 | |
| 375 foreach ($command_array as $k => $v) { | |
| 376 $part = ''; | |
| 377 $next_method = 'unknown'; | |
| 378 | |
| 379 // Lookup next method | |
| 380 if ($k < $cnt-1) { | |
| 381 $next_method = $command_array[$k+1]['method']; | |
| 382 } | |
| 383 | |
| 384 // If previous option was OR, close any open brakets | |
| 385 if ($paranthesis > 0 && $prev_method == 'or' && $v['method'] != 'or') { | |
| 386 for (; $paranthesis > 0; $paranthesis--) { | |
| 387 $part .= ')'; | |
| 388 } | |
| 389 } | |
| 390 | |
| 391 // If there are two consecutive ORs, add brakets | |
| 392 // If the next option is a new OR, add the prefix here | |
| 393 // If the next option is _not_ an OR, and the current option is AND, prefix ALL | |
| 394 if ($next_method == 'or') { | |
| 395 if ($v['method'] == 'or') { | |
| 396 $part .= ' ('; | |
| 397 $paranthesis++; | |
| 398 } | |
| 399 $part .= 'OR '; | |
| 400 } elseif ($v['method'] == 'and') { | |
| 401 $part .= 'ALL '; | |
| 402 } | |
| 403 | |
| 404 $part .= $v['command']; | |
| 405 | |
| 406 // If this is the end of the query, and we have open brakets, close them | |
| 407 if ($k == $cnt-1 && $paranthesis > 0) { | |
| 408 for (; $paranthesis > 0; $paranthesis--) { | |
| 409 $part .= ')'; | |
| 410 } | |
| 411 } | |
| 412 | |
| 413 $prev_method = $v['method']; | |
| 414 $command[] = $part; | |
| 415 } | |
| 416 | |
| 417 $command = implode(' ', $command); | |
| 418 | |
| 419 return $command; | |
| 420 } | |
| 421 | |
| 422 /** | |
| 423 * This functions sends the initial data to the client side where a form (in dialog) is built for the advanced search | |
| 424 * | |
| 425 * @access public | |
| 426 * @return null | |
| 427 */ | |
| 428 public function display_advanced_search() | |
| 429 { | |
| 430 $ret = array('html' => $this->generate_searchbox(), | |
| 431 'row' => $this->add_row(), | |
| 432 'saved_searches' => $this->get_saved_search_names(), | |
| 433 'title' => $this->i18n_strings['advsearch'], | |
| 434 'date_criteria' => $this->config['date_criteria'], | |
| 435 'flag_criteria' => $this->config['flag_criteria'], | |
| 436 'email_criteria' => $this->config['email_criteria']); | |
| 437 | |
| 438 $this->rc->output->command('plugin.show', $ret); | |
| 439 } | |
| 440 | |
| 441 public function generate_searchbox() | |
| 442 { | |
| 443 $search_button = new html_inputfield(array('type' => 'submit', 'name' => 'search', 'class' => 'button mainaction', 'value' => $this->i18n_strings['search'])); | |
| 444 $reset_button = new html_inputfield(array('type' => 'reset', 'name' => 'reset', 'class' => 'button reset', 'value' => $this->i18n_strings['resetsearch'])); | |
| 46 | 445 $save_button = html::tag('input', array('type' => 'submit', 'name' => 'save_the_search', 'id' => 'save_the_search', 'class' => 'button save_search', 'value' => $this->i18n_strings['save_the_search'])); |
| 34 | 446 $delete_button = new html_inputfield(array('type' => 'submit', 'name' => 'delete', 'style' => 'display: none;', 'class' => 'button delete_search', 'value' => $this->i18n_strings['deletesearch'])); |
| 447 | |
| 448 $layout_table = new html_table(); | |
| 449 $layout_table->add(null, $search_button->show()); | |
| 450 $folderConfig = array('name' => 'folder'); | |
| 451 $layout_table->add( | |
| 452 null, | |
| 453 $this->i18n_strings['in'] . ': ' . | |
| 454 $this->folder_selector($folderConfig)->show($this->rc->storage->get_folder()) . | |
| 455 html::span( | |
| 456 array('class' => 'sub-folders'), | |
| 457 $this->i18n_strings['andsubfolders'] . ': ' . | |
| 458 html::tag( | |
| 459 'input', | |
| 460 array('type' => 'checkbox', 'name' => 'subfolder'), | |
| 461 null | |
| 462 ) | |
| 463 ) . | |
| 464 $this->i19n_strings['where'] | |
| 465 ); | |
| 466 $first_row = $this->add_row(true); | |
| 467 $layout_table->add_row(); | |
| 468 $layout_table->add(array('class' => 'adv-search-and-or'), null); | |
| 469 $layout_table->add(null, $first_row); | |
| 470 $layout_table->add_row(); | |
| 471 $layout_table->add(null, $search_button->show()); | |
| 472 $layout_table->add(null, $save_button . ' ' . $reset_button->show() . ' ' . $delete_button->show()); | |
| 473 | |
| 474 return html::tag( | |
| 475 'div', | |
| 476 array('id' => 'adsearch-popup'), | |
| 477 html::tag( | |
| 478 'form', | |
| 479 array('method' => 'post', 'action' => '#'), | |
| 480 $layout_table->show() | |
| 481 ) | |
| 482 ); | |
| 483 } | |
| 484 | |
| 485 /** | |
| 486 * This function is used to render the html of the advanced search form and also | |
| 487 * the later following rows are created by this function | |
| 488 * | |
| 489 * @param array $folders Array of folders | |
| 490 * @param boolean $first True if form gets created, False to create a new row | |
| 491 * @access public | |
| 492 * @return string The final html | |
| 493 */ | |
| 494 public function add_row($first = false) | |
| 495 { | |
| 496 $row_html = ''; | |
| 497 $optgroups = ''; | |
| 498 | |
| 499 $criteria = $this->config['criteria']; | |
| 500 $all_criteria = array( | |
| 501 $this->gettext('Common') => $this->config['prefered_criteria'], | |
| 502 $this->gettext('Addresses') => $this->config['email_criteria'], | |
| 503 $this->gettext('Dates') => $this->config['date_criteria'], | |
| 504 $this->gettext('Flags') => $this->config['flag_criteria'], | |
| 505 $this->gettext('Other') => $this->config['other_criteria'], | |
| 506 ); | |
| 507 | |
| 508 foreach ($all_criteria as $label => $specific_criteria) { | |
| 509 $options = ''; | |
| 510 | |
| 511 foreach ($specific_criteria as $value) { | |
| 512 $options .= html::tag('option', array('value' => $value), $criteria[$value]); | |
| 513 } | |
| 514 | |
| 515 $optgroups .= html::tag('optgroup', array('label' => $label), $options); | |
| 516 } | |
| 517 | |
| 518 $tmp = html::tag('select', array('name' => 'filter'), $optgroups); | |
| 519 $tmp .= $this->i18n_strings['not'] . ':' . html::tag('input', array('type' => 'checkbox', 'name' => 'not'), null); | |
| 520 $tmp .= html::tag('input', array('type' => 'text', 'name' => 'filter-val')); | |
| 521 $tmp .= $this->i18n_strings['exclude'] . ':' . html::tag('input', array('type' => 'checkbox', 'name' => 'filter-exclude'), null); | |
| 522 $tmp .= html::tag('button', array('name' => 'add', 'class' => 'add'), $this->i18n_strings['addfield']); | |
| 523 | |
| 524 if ($first) { | |
| 525 $row_html = $tmp; | |
| 526 } else { | |
| 527 $and_or_select = new html_select(array('name' => 'method')); | |
| 528 $and_or_select->add($this->i18n_strings['and'], 'and'); | |
| 529 $and_or_select->add($this->i18n_strings['or'], 'or'); | |
| 530 $tmp .= html::tag('button', array('name' => 'delete', 'class' => 'delete'), $this->i18n_strings['delete']); | |
| 531 $row_html = html::tag( | |
| 532 'tr', | |
| 533 null, | |
| 534 html::tag( | |
| 535 'td', | |
| 536 array('class' => 'adv-search-and-or'), | |
| 537 $and_or_select->show() | |
| 538 ) . | |
| 539 html::tag( | |
| 540 'td', | |
| 541 null, | |
| 542 $tmp | |
| 543 ) | |
| 544 ); | |
| 545 } | |
| 546 | |
| 547 return $row_html; | |
| 548 } | |
| 549 | |
| 550 /** | |
| 551 * Return folders list as html_select object | |
| 552 * | |
| 553 * This is a copy of the core function and adapted to fit | |
| 554 * the needs of the advanced_search function | |
| 555 * | |
| 556 * @param array $p Named parameters | |
| 557 * | |
| 558 * @return html_select HTML drop-down object | |
| 559 */ | |
| 560 public function folder_selector($p = array()) | |
| 561 { | |
| 562 $p += array('maxlength' => 100, 'realnames' => false, 'is_escaped' => true); | |
| 563 $a_mailboxes = array(); | |
| 564 $storage = $this->rc->get_storage(); | |
| 565 | |
| 566 $list = $storage->list_folders_subscribed(); | |
| 567 $delimiter = $storage->get_hierarchy_delimiter(); | |
| 568 | |
| 569 foreach ($list as $folder) { | |
| 570 $this->rc->build_folder_tree($a_mailboxes, $folder, $delimiter); | |
| 571 } | |
| 572 | |
| 573 $select = new html_select($p); | |
| 574 $select->add($this->i18n_strings['allfolders'], "all"); | |
| 575 | |
| 576 $this->rc->render_folder_tree_select($a_mailboxes, $mbox, $p['maxlength'], $select, $p['realnames'], 0, $p); | |
| 577 | |
| 578 return $select; | |
| 579 } | |
| 580 | |
| 581 public function trigger_search_pagination($param) | |
| 582 { | |
| 583 $_GET['search'] = $_SESSION['av_search']; | |
| 584 $_GET['folder'] = $_SESSION['av_folder']; | |
| 585 $_GET['sub_folders'] = $_SESSION['av_sub_folders']; | |
| 586 $this->trigger_search(true); | |
| 587 } | |
| 588 | |
| 589 /** | |
| 590 * Here is where the actual query is fired to the imap server and the result is evaluated and sent back to the client side | |
| 591 * | |
| 592 * @access public | |
| 593 * @return null | |
| 594 */ | |
| 595 public function trigger_search($inPagination = false) | |
| 596 { | |
| 597 $search = rcube_utils::get_input_value('search', rcube_utils::INPUT_GPC); | |
| 598 // reset list_page and old search results | |
| 599 $this->rc->storage->set_page(1); | |
| 600 $this->rc->storage->set_search_set(null); | |
| 601 $page = rcube_utils::get_input_value('_page', rcube_utils::INPUT_GPC); | |
| 602 $page = $page ? $page : 1; | |
| 603 $pagesize = $this->rc->storage->get_pagesize(); | |
| 604 | |
| 605 if (!empty($search)) { | |
| 606 $mbox = rcube_utils::get_input_value('folder', rcube_utils::INPUT_GPC); | |
|
42
db1e51c59ddc
various small fixes from upgrades to PHP and/or hangover from fix to apt-get overwrite at beginning of the year somehow
Charlie Root
parents:
34
diff
changeset
|
607 $imap_charset = RCUBE_CHARSET; |
| 34 | 608 $sort_column = rcmail_sort_column(); |
| 609 $search_str = $this->get_search_query($search); | |
| 610 $sub_folders = rcube_utils::get_input_value('sub_folders', rcube_utils::INPUT_GPC) == 'true'; | |
| 611 $folders = array(); | |
| 612 $result_h = array(); | |
| 613 $count = 0; | |
| 614 $new_id = 1; | |
| 615 $current_mbox = $this->rc->storage->get_folder(); | |
| 616 $uid_list = array(); | |
| 617 //Store information in session for pagination | |
| 618 $_SESSION['av_search'] = $search; | |
| 619 $_SESSION['av_folder'] = $mbox; | |
| 620 $_SESSION['av_sub_folders'] = rcube_utils::get_input_value('sub_folders', rcube_utils::INPUT_GPC); | |
| 621 $nosub = $sub_folders; | |
| 622 $folders = $this->rc->get_storage()->list_folders_subscribed(); | |
| 623 if (empty($folders) || ($sub_folders === false && $mbox !== 'all')) { | |
| 624 $folders = array($mbox); | |
| 625 } elseif ($mbox !== 'all') { | |
| 626 if ($sub_folders === false) { | |
| 627 $folders = array($mbox); | |
| 628 } else { | |
| 629 $folders = $this->rc->get_storage()->list_folders_subscribed_direct($mbox); | |
| 630 } | |
| 631 } | |
| 632 $md5folders = array(); | |
| 633 foreach ($folders as $folder) { | |
| 634 $md5folders[md5($folder)] = $folder; | |
| 635 } | |
| 636 $this->rc->output->set_env('as_md5_folders', $md5folders); | |
| 637 | |
| 638 if ($search_str) { | |
| 639 $res = $this->perform_search($search_str, $folders, $page); | |
| 640 $count = $res['count']; | |
| 641 } | |
| 642 | |
| 643 | |
| 644 if ($count > 0) { | |
| 645 $_SESSION['advanced_search']['uid_list'] = $uid_list; | |
| 646 if ($search_str && $inPagination == false) { | |
| 647 $this->rc->output->show_message('searchsuccessful', 'confirmation', array('nr' => $count)); | |
| 648 } | |
| 649 } elseif ($err_code = $this->rc->storage->get_error_code()) { | |
| 650 rcmail_display_server_error(); | |
| 651 } else { | |
| 652 $this->rc->output->show_message('searchnomatch', 'notice'); | |
| 653 } | |
| 654 | |
| 655 $current_folder = rcube_utils::get_input_value('current_folder', rcube_utils::INPUT_GPC); | |
| 656 | |
| 657 $this->rc->output->set_env('search_request', 'advanced_search_active'); | |
| 658 $this->rc->output->set_env('messagecount', $count); | |
| 659 $this->rc->output->set_env('pagecount', ceil($count / $pagesize)); | |
| 660 $this->rc->output->set_env('exists', $this->rc->storage->count($current_folder, 'EXISTS')); | |
| 661 $this->rc->output->command('set_rowcount', rcmail_get_messagecount_text($count, $page)); | |
| 662 $this->rc->output->command('plugin.search_complete'); | |
| 663 $this->rc->output->send(); | |
| 664 } | |
| 665 } | |
| 666 | |
| 667 /** | |
| 668 * return javascript commands to add rows to the message list | |
| 669 */ | |
| 670 public function rcmail_js_message_list($a_headers, $insert_top = false, $a_show_cols = null, $avmbox = false, $avcols = array(), $showMboxColumn = false) | |
| 671 { | |
| 672 global $CONFIG, $RCMAIL, $OUTPUT; | |
| 673 $uid_mboxes = array(); | |
| 674 | |
| 675 if (empty($a_show_cols)) { | |
| 676 if (!empty($_SESSION['list_attrib']['columns'])) { | |
| 677 $a_show_cols = $_SESSION['list_attrib']['columns']; | |
| 678 } else { | |
| 679 $a_show_cols = is_array($CONFIG['list_cols']) ? $CONFIG['list_cols'] : array('subject'); | |
| 680 } | |
| 681 } else { | |
| 682 if (!is_array($a_show_cols)) { | |
| 683 $a_show_cols = preg_split('/[\s,;]+/', strip_quotes($a_show_cols)); | |
| 684 } | |
| 685 $head_replace = true; | |
| 686 } | |
| 687 | |
| 688 $mbox = $RCMAIL->storage->get_folder(); | |
| 689 | |
| 690 // make sure 'threads' and 'subject' columns are present | |
| 691 if (!in_array('subject', $a_show_cols)) { | |
| 692 array_unshift($a_show_cols, 'subject'); | |
| 693 } | |
| 694 if (!in_array('threads', $a_show_cols)) { | |
| 695 array_unshift($a_show_cols, 'threads'); | |
| 696 } | |
| 697 $_SESSION['list_attrib']['columns'] = $a_show_cols; | |
| 698 | |
| 699 // Make sure there are no duplicated columns (#1486999) | |
| 700 $a_show_cols = array_merge($a_show_cols, $avcols); | |
| 701 $a_show_cols = array_unique($a_show_cols); | |
| 702 | |
| 703 // Plugins may set header's list_cols/list_flags and other rcube_message_header variables | |
| 704 // and list columns | |
| 705 $plugin = $RCMAIL->plugins->exec_hook( | |
| 706 'messages_list', | |
| 707 array('messages' => $a_headers, 'cols' => $a_show_cols) | |
| 708 ); | |
| 709 $a_show_cols = $plugin['cols']; | |
| 710 $a_headers = $plugin['messages']; | |
| 711 $thead = $head_replace ? rcmail_message_list_head($_SESSION['list_attrib'], $a_show_cols) : null; | |
| 712 | |
| 713 // get name of smart From/To column in folder context | |
| 714 if (($f = array_search('fromto', $a_show_cols)) !== false) { | |
| 715 $smart_col = rcmail_message_list_smart_column_name(); | |
| 716 } | |
| 717 if ($this->coltypesSet == false) { | |
| 718 $OUTPUT->command('set_message_coltypes', $a_show_cols, $thead, $smart_col); | |
| 719 if ($showMboxColumn === true) { | |
| 720 $OUTPUT->command('plugin.advanced_search_add_header', array()); | |
| 721 } | |
| 722 $this->coltypesSet = true; | |
| 723 } | |
| 724 | |
| 725 if (empty($a_headers)) { | |
| 726 return; | |
| 727 } | |
| 728 | |
| 729 // remove 'threads', 'attachment', 'flag', 'status' columns, we don't need them here | |
| 730 foreach (array('threads', 'attachment', 'flag', 'status', 'priority') as $col) { | |
| 731 if (($key = array_search($col, $a_show_cols)) !== false) { | |
| 732 unset($a_show_cols[$key]); | |
| 733 } | |
| 734 } | |
| 735 | |
| 736 // loop through message headers | |
| 737 foreach ($a_headers as $n => $header) { | |
| 738 if (empty($header)) { | |
| 739 continue; | |
| 740 } | |
| 741 $a_msg_cols = array(); | |
| 742 $a_msg_flags = array(); | |
| 743 // format each col; similar as in rcmail_message_list() | |
| 744 foreach ($a_show_cols as $col) { | |
| 745 $col_name = $col == 'fromto' ? $smart_col : $col; | |
| 746 | |
| 747 if (in_array($col_name, array('from', 'to', 'cc', 'replyto'))) { | |
| 748 $cont = rcmail_address_string($header->$col_name, 3, false, null, $header->charset); | |
| 749 } elseif ($col == 'subject') { | |
| 750 $cont = trim(rcube_mime::decode_header($header->$col, $header->charset)); | |
| 751 if (!$cont) { | |
| 752 $cont = $this->gettext('nosubject'); | |
| 753 } | |
| 754 $cont = rcube::Q($cont); | |
| 755 } elseif ($col == 'size') { | |
| 756 $cont = $this->rc->show_bytes($header->$col); | |
| 757 } elseif ($col == 'date') { | |
| 758 $cont = rcube_utils::format_datestr($header->date,$date_format); | |
| 759 } else { | |
| 760 $cont = rcube::Q($header->$col); | |
| 761 } | |
| 762 $a_msg_cols[$col] = $cont; | |
| 763 } | |
| 764 | |
| 765 $a_msg_flags = array_change_key_case(array_map('intval', (array) $header->flags)); | |
| 766 if ($header->depth) { | |
| 767 $a_msg_flags['depth'] = $header->depth; | |
| 768 } elseif ($header->has_children) { | |
| 769 $roots[] = $header->uid; | |
| 770 } | |
| 771 if ($header->parent_uid) { | |
| 772 $a_msg_flags['parent_uid'] = $header->parent_uid; | |
| 773 } | |
| 774 if ($header->has_children) { | |
| 775 $a_msg_flags['has_children'] = $header->has_children; | |
| 776 } | |
| 777 if ($header->unread_children) { | |
| 778 $a_msg_flags['unread_children'] = $header->unread_children; | |
| 779 } | |
| 780 if ($header->others['list-post']) { | |
| 781 $a_msg_flags['ml'] = 1; | |
| 782 } | |
| 783 if ($header->priority) { | |
| 784 $a_msg_flags['prio'] = (int) $header->priority; | |
| 785 } | |
| 786 $a_msg_flags['ctype'] = rcube::Q($header->ctype); | |
| 787 $a_msg_flags['mbox'] = $mbox; | |
| 788 if (!empty($header->list_flags) && is_array($header->list_flags)) { | |
| 789 $a_msg_flags = array_merge($a_msg_flags, $header->list_flags); | |
| 790 } | |
| 791 if (!empty($header->list_cols) && is_array($header->list_cols)) { | |
| 792 $a_msg_cols = array_merge($a_msg_cols, $header->list_cols); | |
| 793 } | |
| 794 if ($showMboxColumn === true) { | |
| 795 $a_msg_flags['avmbox'] = $avmbox; | |
| 796 } | |
| 797 | |
| 798 $OUTPUT->command( | |
| 799 'add_message_row', | |
| 800 $header->uid . '__MB__' . md5($mbox), | |
| 801 $a_msg_cols, | |
| 802 $a_msg_flags, | |
| 803 $insert_top | |
| 804 ); | |
| 805 $id = $header->uid . '__MB__' . md5($mbox); | |
| 806 $uid_mboxes[$id] = array('uid' => $header->uid, 'mbox' => $mbox, 'md5mbox' => md5($mbox)); | |
| 807 } | |
| 808 | |
| 809 if ($RCMAIL->storage->get_threading()) { | |
| 810 $OUTPUT->command('init_threads', (array) $roots, $mbox); | |
| 811 } | |
| 812 | |
| 813 return $uid_mboxes; | |
| 814 } | |
| 815 | |
| 816 | |
| 817 private function do_pagination($folders, $onPage) | |
| 818 { | |
| 819 $perPage = $this->rc->storage->get_pagesize(); | |
| 820 $from = $perPage * $onPage - $perPage + 1; | |
| 821 $to = $from + $perPage - 1; | |
| 822 $got = 0; | |
| 823 $pos = 0; | |
| 824 $cbox = ""; | |
| 825 $boxStart = 0; | |
| 826 $boxStop = 0; | |
| 827 $fetch = array(); | |
| 828 foreach ($folders as $box => $num) { | |
| 829 $i = $num; | |
| 830 if ($box != $cbox) { | |
| 831 $boxStart = 0; | |
| 832 $boxStop = 0; | |
| 833 $cbox = $box; | |
| 834 } | |
| 835 while ($i--) { | |
| 836 $pos++; | |
| 837 $boxStart++; | |
| 838 if ($pos >= $from && $pos <= $to) { | |
| 839 if (!isset($fetch[$box])) { | |
| 840 $fetch[$box] = array("from" => $boxStart); | |
| 841 } | |
| 842 $fetch[$box]['to'] = $boxStart; | |
| 843 $got++; | |
| 844 } | |
| 845 } | |
| 846 if ($got >= $perPage) { | |
| 847 break; | |
| 848 } | |
| 849 } | |
| 850 | |
| 851 return $fetch; | |
| 852 } | |
| 853 | |
| 854 /** | |
| 855 * Save advanced search preferences | |
| 856 * | |
| 857 * @access public | |
| 858 */ | |
| 859 public function preferences_save($args) | |
| 860 { | |
| 861 if ($args['section'] != 'advancedsearch') { | |
| 862 return; | |
| 863 } | |
| 864 $rcmail = rcmail::get_instance(); | |
| 865 | |
| 866 $displayOptions = array(); | |
| 867 $displayOptions['_show_message_label_header'] = rcube_utils::get_input_value('_show_message_label_header', rcube_utils::INPUT_POST) == 1 ? true : false; | |
| 868 $displayOptions['_show_message_mbox_info'] = rcube_utils::get_input_value('_show_message_mbox_info', rcube_utils::INPUT_POST) == 1 ? true : false; | |
| 869 $displayOptions['target_menu'] = rcube_utils::get_input_value('button_display_option', rcube_utils::INPUT_POST); | |
| 870 | |
| 871 $args['prefs']['advanced_search_display_options'] = $displayOptions; | |
| 872 | |
| 873 return($args); | |
| 874 } | |
| 875 | |
| 876 /** | |
| 877 * Add a section advanced search to the preferences section list | |
| 878 * | |
| 879 * @access public | |
| 880 */ | |
| 881 public function preferences_section($args) | |
| 882 { | |
| 883 $args['list']['advancedsearch'] = array( | |
| 884 'id' => 'advancedsearch', | |
| 885 'section' => rcube::Q($this->gettext('advancedsearch')) | |
| 886 ); | |
| 887 | |
| 888 return($args); | |
| 889 } | |
| 890 | |
| 891 /** | |
| 892 * Display advanced search configuration in user preferences tab | |
| 893 * | |
| 894 * @access public | |
| 895 */ | |
| 896 public function preferences_list($args) | |
| 897 { | |
| 898 if ($args['section'] == 'advancedsearch') { | |
| 899 | |
| 900 $this->rc = rcmail::get_instance(); | |
| 901 $args['blocks']['label_display_options'] = array('options' => array(), 'name' => rcube::Q($this->gettext('label_display_options'))); | |
| 902 | |
| 903 $displayOptions = $this->rc->config->get('advanced_search_display_options', array()); | |
| 904 $target_menu = (isset($displayOptions['target_menu']) && !empty($displayOptions['target_menu'])) ? $displayOptions['target_menu'] : $this->config['target_menu']; | |
| 905 $options = ''; | |
| 906 $optarg = array('value' => 'messagemenu'); | |
| 907 if ($target_menu == 'messagemenu') { | |
| 908 $optarg['selected'] = 'selected'; | |
| 909 $target_image = 'menu_location_a.jpg'; | |
| 910 } | |
| 911 $options .= html::tag('option', $optarg, rcube::Q($this->gettext('display_in_messagemenu'))); | |
| 912 $optarg = array('value' => 'toolbar'); | |
| 913 if ($target_menu == 'toolbar') { | |
| 914 $optarg['selected'] = 'selected'; | |
| 915 $target_image = 'menu_location_b.jpg'; | |
| 916 } | |
| 917 $options .= html::tag('option', $optarg,rcube::Q($this->gettext('display_in_toolbar'))); | |
| 918 $select = html::tag('select', array('name' => 'button_display_option', 'id' => 'button_display_option'), $options); | |
| 919 | |
| 920 $label1 = html::label('_show_message_label_header', rcube::Q($this->gettext('mailbox_headers_in_results'))); | |
| 921 $label2 = html::label('_show_message_mbox_info', rcube::Q($this->gettext('mailbox_info_in_results'))); | |
| 922 $label3 = html::label('button_display_option', rcube::Q($this->gettext('show_advanced_search'))); | |
| 923 | |
| 924 $arg1 = array('name' => '_show_message_label_header', 'id' => '_show_message_label_header', 'type' => 'checkbox', 'title' => "", 'class' => 'watermark linput', 'value' => 1); | |
| 925 if (isset($displayOptions['_show_message_label_header']) && $displayOptions['_show_message_label_header'] === true) { | |
| 926 $arg1['checked'] = 'checked'; | |
| 927 $img1class = 'enabled'; | |
| 928 } else { | |
| 929 $img1class = 'disabled'; | |
| 930 } | |
| 931 $check1 = html::tag('input', $arg1); | |
| 932 $arg2 = array('name' => '_show_message_mbox_info', 'id' => '_show_message_mbox_info', 'type' => 'checkbox', 'title' => "", 'class' => 'watermark linput', 'value' => 1); | |
| 933 if (isset($displayOptions['_show_message_mbox_info']) && $displayOptions['_show_message_mbox_info'] === true) { | |
| 934 $arg2['checked'] = 'checked'; | |
| 935 $img2class = 'enabled'; | |
| 936 } else { | |
| 937 $img2class = 'disabled'; | |
| 938 } | |
| 939 | |
| 940 $img1 = html::img(array('src' => $this->url('skins/larry/images/show_mbox_row.jpg'), 'class' => $img1class)); | |
| 941 $img2 = html::img(array('src' => $this->url('skins/larry/images/show_mbox_col.jpg'), 'class' => $img2class)); | |
| 942 $img3 = html::img(array('src' => $this->url('skins/larry/images/' . $target_image))); | |
| 943 | |
| 944 $check2 = html::tag('input', $arg2); | |
| 945 $args['blocks']['label_display_options']['options'][0] = array('title' => '', 'content' => '<p class="avsearchpref"><span>' . $check1 . ' ' . $label1 . '</span> ' . $img1 . '</p>'); | |
| 946 $args['blocks']['label_display_options']['options'][1] = array('title' => '', 'content' => '<p class="avsearchpref"><span>' . $check2 . ' ' . $label2 . '</span> ' . $img2 . '</p>'); | |
| 947 $args['blocks']['label_display_options']['options'][2] = array('title' => '', 'content' => '<p class="avsearchpref"><span>' . $label3 . ' ' . $select . '</span> ' . $img3 . '</p>'); | |
| 948 } | |
| 949 | |
| 950 return($args); | |
| 951 } | |
| 952 | |
| 953 private function perform_search($search_string, $folders, $page = 1) | |
| 954 { | |
| 955 // Search all folders and build a final set | |
| 956 if ($folders[0] == 'all' || empty($folders)) { | |
| 957 $folders_search = $this->rc->imap->list_folders_subscribed(); | |
| 958 } else { | |
| 959 $folders_search = $folders; | |
| 960 } | |
| 961 $count = 0; | |
| 962 $folder_count = array(); | |
| 963 foreach ($folders_search as $mbox) { | |
| 964 $this->rc->storage->set_folder($mbox); | |
|
42
db1e51c59ddc
various small fixes from upgrades to PHP and/or hangover from fix to apt-get overwrite at beginning of the year somehow
Charlie Root
parents:
34
diff
changeset
|
965 $this->rc->storage->search($mbox, $search_string, RCUBE_CHARSET, $_SESSION['sort_col']); |
| 34 | 966 $result = array(); |
| 967 $fcount = $this->rc->storage->count($mbox, 'ALL', !empty($_REQUEST['_refresh'])); | |
| 968 $count += $fcount; | |
| 969 $folder_count[$mbox] = $fcount; | |
| 970 } | |
| 971 foreach ($folder_count as $k => $v) { | |
| 972 if ($v == 0) { | |
| 973 unset($folder_count[$k]); | |
| 974 } | |
| 975 } | |
| 976 $fetch = $this->do_pagination($folder_count, $page); | |
| 977 $mails = array(); | |
| 978 $currentMailbox = ""; | |
| 979 $displayOptions = $this->rc->config->get('advanced_search_display_options', array()); | |
| 980 $showMboxColumn = isset($displayOptions['_show_message_mbox_info']) && $displayOptions['_show_message_mbox_info'] ? true : false; | |
| 981 $uid_mboxes = array(); | |
| 982 foreach ($fetch as $mailbox => $data) { | |
| 983 if ($currentMailbox != $mailbox) { | |
| 984 $currentMailbox = $mailbox; | |
| 985 if (isset($displayOptions['_show_message_label_header']) && $displayOptions['_show_message_label_header'] === true) { | |
| 986 $this->rc->output->command('advanced_search_add_mbox', $mailbox, $folder_count[$mailbox], $showMboxColumn); | |
| 987 } | |
| 988 } | |
| 989 $uid_mboxes = array_merge($uid_mboxes, $this->getMails($mailbox, $data, $search_string, $showMboxColumn)); | |
| 990 } | |
| 991 | |
| 992 return array('result' => array(), 'count' => $count, 'uid_mboxes' => $uid_mboxes); | |
| 993 } | |
| 994 | |
| 995 private function getMails($mailbox, $data, $search_string, $showMboxColumn) | |
| 996 { | |
| 997 $pageSize = $this->rc->storage->get_pagesize(); | |
| 998 $msgNum = $data['from']; | |
| 999 $startPage = ceil($msgNum/$pageSize); | |
| 1000 $msgMod = $msgNum % $pageSize; | |
| 1001 $multiPage = "false"; | |
| 1002 $firstArrayElement = $msgMod == 0 ? ($pageSize-1) : ($msgMod-1); | |
| 1003 $quantity = $data['to'] - $data['from']; | |
| 1004 if ($data['from'] + $quantity > $pageSize) { | |
| 1005 $multiPage = "true"; | |
| 1006 } | |
| 1007 $this->rc->storage->set_folder($mailbox); | |
|
42
db1e51c59ddc
various small fixes from upgrades to PHP and/or hangover from fix to apt-get overwrite at beginning of the year somehow
Charlie Root
parents:
34
diff
changeset
|
1008 $this->rc->storage->search($mailbox, $search_string, RCUBE_CHARSET, $_SESSION['sort_col']); |
| 34 | 1009 $messages = $this->rc->storage->list_messages('', $startPage); |
| 1010 if ($multiPage) { | |
| 1011 $messages = array_merge($messages, $this->rc->storage->list_messages('', $startPage+1)); | |
| 1012 } | |
| 1013 //FIRST: 0 QUANTITY: 2 | |
| 1014 $sliceTo = $quantity + 1; | |
| 1015 $mslice = array_slice($messages, $firstArrayElement, $sliceTo, true); | |
| 1016 $messages = $mslice; | |
| 1017 $avbox = array(); | |
| 1018 $showAvmbox = false; | |
| 1019 foreach ($messages as $set_flag) { | |
| 1020 $set_flag->flags['skip_mbox_check'] = true; | |
| 1021 if ($showMboxColumn === true) { | |
| 1022 $set_flag->avmbox = $mailbox; | |
| 1023 $avbox[] = 'avmbox'; | |
| 1024 $showAvmbox = true; | |
| 1025 } | |
| 1026 } | |
| 1027 $uid_mboxes = $this->rcmail_js_message_list($messages, false, null, $showAvmbox, $avbox, $showMboxColumn); | |
| 1028 | |
| 1029 return $uid_mboxes; | |
| 1030 } | |
| 1031 | |
| 1032 public function save_search() | |
| 1033 { | |
| 1034 $search_name = rcube_utils::get_input_value('search_name', rcube_utils::INPUT_GPC); | |
| 1035 if ($search_name) { | |
| 1036 $search = array(); | |
| 1037 $search['search'] = rcube_utils::get_input_value('search', rcube_utils::INPUT_GPC); | |
| 1038 $search['search_name'] = $search_name; | |
| 1039 $search['folder'] = rcube_utils::get_input_value('folder', rcube_utils::INPUT_GPC); | |
| 1040 $search['sub_folders'] = rcube_utils::get_input_value('sub_folders', rcube_utils::INPUT_GPC); | |
| 1041 $prefs = (array)$this->rc->user->get_prefs(); | |
| 1042 if (!isset($prefs['advanced_search'])) { | |
| 1043 $prefs['advanced_search'] = array(); | |
| 1044 } | |
| 1045 $prefs['advanced_search'][$search_name] = $search; | |
| 1046 $this->rc->user->save_prefs(array('advanced_search' => $prefs['advanced_search'])); | |
| 1047 $this->rc->output->show_message('"<i>' . $search_name . '</i>" ' . $this->i18n_strings['has_been_saved'], 'confirmation'); | |
| 1048 } | |
| 1049 } | |
| 1050 | |
| 1051 public function delete_search() | |
| 1052 { | |
| 1053 $search_name = rcube_utils::get_input_value('search_name', rcube_utils::INPUT_GPC); | |
| 1054 if ($search_name) { | |
| 1055 $prefs = (array)$this->rc->user->get_prefs(); | |
| 1056 unset($prefs['advanced_search'][$search_name]); | |
| 1057 $this->rc->user->save_prefs(array('advanced_search' => $prefs['advanced_search'])); | |
| 1058 $this->rc->output->show_message('"<i>' . $search_name . '</i>" ' . $this->i18n_strings['has_been_deleted'], 'notice'); | |
| 1059 } | |
| 1060 } | |
| 1061 | |
| 1062 public function get_saved_search() | |
| 1063 { | |
| 1064 $search_name = rcube_utils::get_input_value('search_name', rcube_utils::INPUT_GPC); | |
| 1065 $prefs = (array)$this->rc->user->get_prefs(); | |
| 1066 if (!isset($prefs['advanced_search'])) { | |
| 1067 $prefs['advanced_search'] = array(); | |
| 1068 } | |
| 1069 | |
| 1070 $search = isset($prefs['advanced_search'][$search_name]) ? $prefs['advanced_search'][$search_name] : false; | |
| 1071 $this->rc->output->command('plugin.load_saved_search', $search); | |
| 1072 $this->rc->output->send(); | |
| 1073 } | |
| 1074 | |
| 1075 private function get_saved_search_names() | |
| 1076 { | |
| 1077 $prefs = (array)$this->rc->user->get_prefs(); | |
| 1078 if (!isset($prefs['advanced_search'])) { | |
| 1079 $prefs['advanced_search'] = array(); | |
| 1080 } | |
| 1081 $names = array(); | |
| 1082 foreach($prefs['advanced_search'] as $name => $search) { | |
| 1083 $names[] = $name; | |
| 1084 } | |
| 1085 | |
| 1086 return $names; | |
| 1087 } | |
| 1088 } |
