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