[ Index ]
 

Code source de IMP H3 (4.1.5)

Accédez au Source d'autres logiciels libres

Classes | Fonctions | Variables | Constantes | Tables

title

Body

[fermer]

/lib/ -> Search.php (source)

   1  <?php
   2  
   3  /* Defines used to determine what kind of field query we are dealing with. */
   4  define('IMP_SEARCH_HEADER', 1);
   5  define('IMP_SEARCH_BODY', 2);
   6  define('IMP_SEARCH_DATE', 3);
   7  define('IMP_SEARCH_TEXT', 4);
   8  
   9  /* Defines used to identify the flag input. */
  10  define('IMP_SEARCH_FLAG_SEEN', 1);
  11  define('IMP_SEARCH_FLAG_ANSWERED', 2);
  12  define('IMP_SEARCH_FLAG_FLAGGED', 3);
  13  define('IMP_SEARCH_FLAG_DELETED', 4);
  14  
  15  /* Defines used to identify whether to show unsubscribed folders. */
  16  define('IMP_SEARCH_SHOW_UNSUBSCRIBED', 0);
  17  define('IMP_SEARCH_SHOW_SUBSCRIBED_ONLY', 1);
  18  
  19  /**
  20   * The IMP_Search:: class contains all code related to mailbox searching
  21   * in IMP.
  22   *
  23   * The class uses the $_SESSION['imp']['search'] variable to store information
  24   * across page accesses. The format of that entry is as follows:
  25   *
  26   * $_SESSION['imp']['search'] = array(
  27   *     'q' => array(
  28   *         'id_1' => array(
  29   *             'query' => IMAP_Search_Query object (serialized),
  30   *             'folders' => array (List of folders to search),
  31   *             'uiinfo' => array (Info used by search.php to render page),
  32   *             'label' => string (Description of search),
  33   *             'vfolder' => boolean (True if this is a Virtual Folder)
  34   *         ),
  35   *         'id_2' => array(
  36   *             ....
  37   *         ),
  38   *         ....
  39   *     ),
  40   *     'vtrash_id' => string (The Virtual Trash query ID),
  41   *     'vinbox_id' => string (The Virtual Inbox query ID)
  42   * );
  43   *
  44   * $Horde: imp/lib/Search.php,v 1.37.10.37 2007/01/02 13:54:56 jan Exp $
  45   *
  46   * Copyright 2002-2007 Michael Slusarz <slusarz@bigworm.colorado.edu>
  47   *
  48   * See the enclosed file COPYING for license information (GPL). If you
  49   * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
  50   *
  51   * @author  Michael Slusarz <slusarz@bigworm.colorado.edu>
  52   * @since   IMP 4.0
  53   * @package IMP
  54   */
  55  class IMP_Search {
  56  
  57      /**
  58       * The ID of the current search query in use.
  59       *
  60       * @var string
  61       */
  62      var $_id = null;
  63  
  64      /**
  65       * The IMP_Tree:: object to update.
  66       *
  67       * @var object
  68       */
  69      var $_imptree;
  70  
  71      /**
  72       * Save Virtual Folder information when adding entries?
  73       *
  74       * @var boolean
  75       */
  76      var $_saveVFolder = true;
  77  
  78      /**
  79       * Constructor.
  80       *
  81       * @param array $params  Available parameters:
  82       * <pre>
  83       * 'id'  --  The ID of the search query in use.
  84       * </pre>
  85       */
  86      function IMP_Search($params = array())
  87      {
  88          if (!empty($params['id'])) {
  89              $this->_id = $this->_strip($params['id']);
  90          }
  91      }
  92  
  93      /**
  94       * Set up IMP_Search variables for the current session.
  95       */
  96      function sessionSetup()
  97      {
  98          if (!isset($_SESSION['imp']['search'])) {
  99              $_SESSION['imp']['search'] = array('q' => array());
 100          }
 101          foreach ($this->_getVFolderList() as $key => $val) {
 102              if (!empty($val['vfolder']) &&
 103                  !$this->isVTrashFolder($key) &&
 104                  !$this->isVINBOXFolder($key)) {
 105                  $_SESSION['imp']['search']['q'][$key] = $val;
 106                  $this->_updateIMPTree('add', $key, $val['label']);
 107              }
 108          }
 109          $this->createVINBOXFolder();
 110          $this->createVTrashFolder();
 111      }
 112  
 113      /**
 114       * Run a search.
 115       *
 116       * @param IMAP_Search_Query &$ob  An optional search query to add (via
 117       *                                'AND') to the active search.
 118       * @param string $id              The search query id to use (by default,
 119       *                                will use the current ID set in the
 120       *                                object).
 121       *
 122       * @return array  The sorted list.
 123       */
 124      function runSearch(&$ob, $id = null)
 125      {
 126          $id = (is_null($id)) ? $this->_id : $this->_strip($id);
 127          $mbox = '';
 128          $sorted = array();
 129          $use_pop3 = ($_SESSION['imp']['base_protocol'] == 'pop3');
 130  
 131          if (empty($_SESSION['imp']['search']['q'][$id])) {
 132              return $sorted;
 133          }
 134          $search = &$_SESSION['imp']['search']['q'][$id];
 135  
 136          $charset = NLS::getCharset();
 137          $search_params = array('pop3' => $use_pop3, 'charset' => $charset);
 138  
 139          /* Check if the IMAP server supports searches in the current
 140           * charset. */
 141          if (empty($_SESSION['imp']['imap_server']['search_charset'][$charset])) {
 142              $search_params['no_imap_charset'] = true;
 143          }
 144  
 145          require_once  IMP_BASE . '/lib/IMAP/Search.php';
 146          $imap_search = &IMP_IMAP_Search::singleton($search_params);
 147  
 148          /* Prepare the search query. */
 149          if (!empty($ob)) {
 150              $old_query = unserialize($search['query']);
 151              $query = &new IMP_IMAP_Search_Query();
 152              $query->imapAnd(array($ob, $old_query));
 153          } else {
 154              $query = unserialize($search['query']);
 155          }
 156  
 157          /* How do we want to sort results? */
 158          $sortby = $GLOBALS['prefs']->getValue('sortby');
 159          if ($sortby == SORTTHREAD) {
 160              $sortby = SORTDATE;
 161          }
 162          $sortdir = $GLOBALS['prefs']->getValue('sortdir');
 163  
 164          foreach ($search['folders'] as $val) {
 165              $results = $imap_search->searchSortMailbox($query, $_SESSION['imp']['stream'], $val, $sortby, $sortdir);
 166  
 167              if (is_array($results)) {
 168                  foreach ($results as $val2) {
 169                      $sorted[] = $val2 . IMP_IDX_SEP . $val;
 170                  }
 171              }
 172          }
 173  
 174          return $sorted;
 175      }
 176  
 177      /**
 178       * Creates the IMAP search query in the IMP session.
 179       *
 180       * @param IMAP_Search_Query $query  The search query object.
 181       * @param array $folders            The list of folders to search.
 182       * @param array $search             The search array used to build the
 183       *                                  search UI screen.
 184       * @param string $label             The label to use for the search
 185       *                                  results.
 186       * @param string $id                The query id to use (or else one is
 187       *                                  automatically generated).
 188       *
 189       * @return string  Returns the search query id.
 190       */
 191      function createSearchQuery($query, $folders, $search, $label, $id = null)
 192      {
 193          $id = (empty($id)) ? base_convert(microtime() . mt_rand(), 16, 36) : $this->_strip($id);
 194          $_SESSION['imp']['search']['q'][$id] = array(
 195              'query' => serialize($query),
 196              'folders' => $folders,
 197              'uiinfo' => $search,
 198              'label' => $label,
 199              'vfolder' => false
 200          );
 201          return $id;
 202      }
 203  
 204      /**
 205       * Deletes an IMAP search query.
 206       *
 207       * @param string $id  The search query id to use (by default, will use
 208       *                    the current ID set in the object).
 209       *
 210       * @return string  Returns the search query id.
 211       */
 212      function deleteSearchQuery($id = null)
 213      {
 214          $id = (is_null($id)) ? $this->_id : $this->_strip($id);
 215          $is_vfolder = !empty($_SESSION['imp']['search']['q'][$id]['vfolder']);
 216          unset($_SESSION['imp']['search']['q'][$id]);
 217  
 218          if ($is_vfolder) {
 219              $vfolders = $this->_getVFolderList();
 220              unset($vfolders[$id]);
 221              $this->_saveVFolderList($vfolders);
 222              $this->_updateIMPTree('delete', $id);
 223          }
 224      }
 225  
 226      /**
 227       * Retrieves the previously stored search UI information.
 228       *
 229       * @param string $id  The search query id to use (by default, will use
 230       *                    the current ID set in the object).
 231       *
 232       * @return array  The array necessary to rebuild the search UI page.
 233       */
 234      function retrieveUIQuery($id = null)
 235      {
 236          $id = (is_null($id)) ? $this->_id : $this->_strip($id);
 237          return (isset($_SESSION['imp']['search']['q'][$id]['uiinfo']))
 238              ? $GLOBALS['imp']['search']['q'][$id]['uiinfo']
 239              : array();
 240      }
 241  
 242      /**
 243       * Generates the label to use for search results.
 244       *
 245       * @param string $id  The search query id to use (by default, will use
 246       *                    the current ID set in the object).
 247       *
 248       * @return string  The search results label.
 249       */
 250      function getLabel($id = null)
 251      {
 252          $id = (is_null($id)) ? $this->_id : $this->_strip($id);
 253          return (isset($_SESSION['imp']['search']['q'][$id]['label']))
 254              ? $GLOBALS['imp']['search']['q'][$id]['label']
 255              : '';
 256      }
 257  
 258      /**
 259       * Obtains the list of virtual folders for the current user.
 260       *
 261       * @access private
 262       *
 263       * @return array  The list of virtual folders.
 264       */
 265      function _getVFolderList()
 266      {
 267          $vfolder = $GLOBALS['prefs']->getValue('vfolder');
 268          if (empty($vfolder)) {
 269              return array();
 270          }
 271  
 272          $vfolder = @unserialize($vfolder);
 273          if (!is_array($vfolder)) {
 274              return array();
 275          }
 276  
 277          $elt = reset($vfolder);
 278          if (!isset($elt['ob'])) {
 279              // Already in 4.1+ format.
 280              return $vfolder;
 281          }
 282  
 283          // Convert from 4.0 format to 4.1+ format, if necessary
 284          $convert = array();
 285          foreach ($vfolder as $key => $val) {
 286              $convert[$key] = array(
 287                  'query' => $val['ob'],
 288                  'folders' => $val['search']['folders'],
 289                  'uiinfo' => $val['search'],
 290                  'label' => $val['search']['vfolder_label'],
 291                  'vfolder' => true
 292              );
 293              unset($convert[$key]['search']['folders'], $convert[$key]['search']['vfolder_label']);
 294          }
 295          return $convert;
 296      }
 297  
 298      /**
 299       * Saves the list of virtual folders for the current user.
 300       *
 301       * @access private
 302       *
 303       * @param array  The virtual folder list.
 304       */
 305      function _saveVFolderList($vfolder)
 306      {
 307          $GLOBALS['prefs']->setValue('vfolder', serialize($vfolder));
 308      }
 309  
 310      /**
 311       * Add a virtual folder for the current user.
 312       *
 313       * @param IMAP_Search_Query $query  The search query object.
 314       * @param array $folders            The list of folders to search.
 315       * @param array $search             The search array used to build the
 316       *                                  search UI screen.
 317       * @param string $label             The label to use for the search
 318       *                                  results.
 319       * @param string $id                The virtual folder id.
 320       *
 321       * @return string  The virtual folder ID.
 322       */
 323      function addVFolder($query, $folders, $search, $label, $id = null)
 324      {
 325          $id = $this->createSearchQuery($query, $folders, $search, $label, $id);
 326          $_SESSION['imp']['search']['q'][$id]['vfolder'] = true;
 327          if ($this->_saveVFolder) {
 328              $vfolders = $this->_getVFolderList();
 329              $vfolders[$id] = $_SESSION['imp']['search']['q'][$id];
 330              $this->_saveVFolderList($vfolders);
 331          }
 332          $this->_updateIMPTree('add', $id, $label);
 333          return $id;
 334      }
 335  
 336      /**
 337       * Add a virtual trash folder for the current user.
 338       */
 339      function createVTrashFolder()
 340      {
 341          /* Delete the current Virtual Trash folder, if it exists. */
 342          $vtrash_id = $GLOBALS['prefs']->getValue('vtrash_id');
 343          if (!empty($vtrash_id)) {
 344              $this->deleteSearchQuery($vtrash_id);
 345          }
 346  
 347          if (!$GLOBALS['prefs']->getValue('use_vtrash')) {
 348              return;
 349          }
 350  
 351          /* Create Virtual Trash with new folder list. */
 352          require_once  IMP_BASE . '/lib/Folder.php';
 353          $imp_folder = &IMP_Folder::singleton();
 354          $fl = $imp_folder->flist_IMP();
 355          $flist = array();
 356          foreach ($fl as $mbox) {
 357              if (!empty($mbox['val'])) {
 358                  $flist[] = $mbox['val'];
 359              }
 360          }
 361          array_unshift($flist, 'INBOX');
 362  
 363          require_once  IMP_BASE . '/lib/IMAP/Search.php';
 364          $query = &new IMP_IMAP_Search_query();
 365          $query->deleted(true);
 366          $label = _("Virtual Trash");
 367  
 368          $this->_saveVFolder = false;
 369          if (empty($vtrash_id)) {
 370              $vtrash_id = $this->addVFolder($query, $flist, array(), $label);
 371              $GLOBALS['prefs']->setValue('vtrash_id', $vtrash_id);
 372          } else {
 373              $this->addVFolder($query, $flist, array(), $label, $vtrash_id);
 374          }
 375          $this->_saveVFolder = true;
 376          $_SESSION['imp']['search']['vtrash_id'] = $vtrash_id;
 377      }
 378  
 379      /**
 380       * Determines whether a virtual folder ID is the Virtual Trash Folder.
 381       *
 382       * @param string $id  The search query id to use (by default, will use
 383       *                    the current ID set in the object).
 384       *
 385       * @return boolean  True if the virutal folder ID is the Virtual Trash
 386       *                  folder.
 387       */
 388      function isVTrashFolder($id = null)
 389      {
 390          $id = (is_null($id)) ? $this->_id : $this->_strip($id);
 391          $vtrash_id = $GLOBALS['prefs']->getValue('vtrash_id');
 392          return (!empty($vtrash_id) && ($id == $vtrash_id));
 393      }
 394  
 395      /**
 396       * Add a virtual INBOX folder for the current user.
 397       */
 398      function createVINBOXFolder()
 399      {
 400          /* Initialize IMP_Tree. */
 401          require_once  IMP_BASE . '/lib/IMAP/Tree.php';
 402          $imptree = &IMP_Tree::singleton();
 403  
 404          /* Delete the current Virtual Trash folder, if it exists. */
 405          $vinbox_id = $GLOBALS['prefs']->getValue('vinbox_id');
 406          if (!empty($vinbox_id)) {
 407              $this->deleteSearchQuery($vinbox_id);
 408          }
 409  
 410          if (!$GLOBALS['prefs']->getValue('use_vinbox')) {
 411              return;
 412          }
 413  
 414          /* Create Virtual INBOX with nav_poll list. Filter out any nav_poll
 415           * entries that don't exist. */
 416          $flist = array_values(array_intersect(array_keys($imptree->getPollList()), $imptree->folderList()));
 417  
 418          /* Sort Virtual INBOX list. */
 419          require_once  IMP_BASE . '/lib/IMAP/Sort.php';
 420          $ns_new = IMP::getNamespace();
 421          $imap_sort = new IMP_IMAP_Sort($ns_new['delimiter']);
 422          $imap_sort->sortMailboxes($flist);
 423  
 424          require_once  IMP_BASE . '/lib/IMAP/Search.php';
 425          $query = &new IMP_IMAP_Search_query();
 426          $query->seen(false);
 427          $query->deleted(false);
 428          $label = _("Virtual INBOX");
 429  
 430          $this->_saveVFolder = false;
 431          if (empty($vinbox_id)) {
 432              $vinbox_id = $this->addVFolder($query, $flist, array(), $label);
 433              $GLOBALS['prefs']->setValue('vinbox_id', $vinbox_id);
 434          } else {
 435              $this->addVFolder($query, $flist, array(), $label, $vinbox_id);
 436          }
 437          $this->_saveVFolder = true;
 438          $_SESSION['imp']['search']['vinbox_id'] = $vinbox_id;
 439      }
 440  
 441      /**
 442       * Determines whether a virtual folder ID is the Virtual INBOX Folder.
 443       *
 444       * @param string $id  The search query id to use (by default, will use
 445       *                    the current ID set in the object).
 446       *
 447       * @return boolean  True if the virutal folder ID is the Virtual INBOX
 448       *                  folder.
 449       */
 450      function isVINBOXFolder($id = null)
 451      {
 452          $id = (is_null($id)) ? $this->_id : $this->_strip($id);
 453          $vinbox_id = $GLOBALS['prefs']->getValue('vinbox_id');
 454          return (!empty($vinbox_id) && ($id == $vinbox_id));
 455      }
 456  
 457      /**
 458       * Is the current active folder an editable Virtual Folder?
 459       *
 460       * @param string $id  The search query id to use (by default, will use
 461       *                    the current ID set in the object).
 462       *
 463       * @return boolean  True if the current folder is both a virtual folder
 464       *                  and can be edited.
 465       */
 466      function isEditableVFolder($id = null)
 467      {
 468          $id = (is_null($id)) ? $this->_id : $this->_strip($id);
 469          return ($this->isVFolder($id) && !$this->isVTrashFolder($id) && !$this->isVINBOXFolder($id));
 470      }
 471  
 472      /**
 473       * Return a list of IDs and query labels, sorted by the label.
 474       *
 475       * @param boolean $vfolder  If true, only return Virtual Folders?
 476       *
 477       * @return array  An array with the folder IDs as the key and the labels
 478       *                as the value.
 479       */
 480      function listQueries($vfolder = false)
 481      {
 482          $vfolders = array();
 483  
 484          if (empty($_SESSION['imp']['search']['q'])) {
 485              return $vfolders;
 486          }
 487  
 488          foreach ($_SESSION['imp']['search']['q'] as $key => $val) {
 489              if (!$vfolder || !empty($val['vfolder'])) {
 490                  $vfolders[$key] = $this->getLabel($key);
 491              }
 492          }
 493          natcasesort($vfolders);
 494  
 495          return $vfolders;
 496      }
 497  
 498      /**
 499       * Get the list of searchable folders for the given search query.
 500       *
 501       * @param string $id  The search query id to use (by default, will use
 502       *                    the current ID set in the object).
 503       *
 504       * @return array  The list of searchable folders.
 505       */
 506      function getSearchFolders($id = null)
 507      {
 508          $id = (is_null($id)) ? $this->_id : $this->_strip($id);
 509          return (isset($_SESSION['imp']['search']['q'][$id]['folders'])) ? $_SESSION['imp']['search']['q'][$id]['folders'] : array();
 510      }
 511  
 512      /**
 513       * Returns a link to edit a given search query.
 514       *
 515       * @param string $id  The search query id to use (by default, will use
 516       *                    the current ID set in the object).
 517       *
 518       * @rerturn string  The URL to the search page.
 519       */
 520      function editURL($id = null)
 521      {
 522          $id = (is_null($id)) ? $this->_id : $this->_strip($id);
 523          return Util::addParameter(Horde::applicationUrl('search.php'), array('edit_query' => $id));
 524      }
 525  
 526      /**
 527       * Returns a link to delete a given search query.
 528       *
 529       * @param string $id  The search query id to use (by default, will use
 530       *                    the current ID set in the object).
 531       *
 532       * @return string  The URL to allow deletion of the search query.
 533       */
 534      function deleteURL($id = null)
 535      {
 536          $id = (is_null($id)) ? $this->_id : $this->_strip($id);
 537          return Util::addParameter(Horde::applicationUrl('folders.php'), array('actionID' => 'delete_search_query', 'queryid' => $id));
 538      }
 539  
 540      /**
 541       * Is the given mailbox a search mailbox?
 542       *
 543       * @param string $id  The search query id to use (by default, will use
 544       *                    the current ID set in the object).
 545       *
 546       * @return boolean  Whether the given mailbox name is a search mailbox.
 547       */
 548      function isSearchMbox($id = null)
 549      {
 550          return (is_null($id)) ? !empty($this->_id) : isset($_SESSION['imp']['search']['q'][$this->_strip($id)]);
 551      }
 552  
 553      /**
 554       * Is the given mailbox a virtual folder?
 555       *
 556       * @param string $id  The search query id to use (by default, will use
 557       *                    the current ID set in the object).
 558       *
 559       * @return boolean  Whether the given mailbox name is a virtual folder.
 560       */
 561      function isVFolder($id = null)
 562      {
 563          $id = (is_null($id)) ? $this->_id : $this->_strip($id);
 564          return (!empty($_SESSION['imp']['search']['q'][$id]['vfolder']));
 565      }
 566  
 567      /**
 568       * Get the ID for the search mailbox, if we are currently in a search
 569       * mailbox.
 570       *
 571       * @return mixed  The search ID if in a mailbox, else false.
 572       */
 573      function searchMboxID()
 574      {
 575          return (!is_null($this->_id)) ? $this->_id : false;
 576      }
 577  
 578      /**
 579       * Strip the identifying label from a mailbox ID.
 580       *
 581       * @access private
 582       *
 583       * @param string $id  The mailbox query ID.
 584       *
 585       * @return string  The virtual folder ID, with any IMP specific identifying
 586       *                 information stripped off.
 587       */
 588      function _strip($id)
 589      {
 590          return (strpos($id, IMP_SEARCH_MBOX) === 0) ? substr($id, strlen(IMP_SEARCH_MBOX)) : $id;
 591      }
 592  
 593      /**
 594       * Create the canonical search ID for a given search query.
 595       *
 596       * @since IMP 4.1.2
 597       *
 598       * @access public
 599       *
 600       * @param string $id  The mailbox query ID.
 601       *
 602       * @return string  The canonical search query ID.
 603       */
 604      function createSearchID($id)
 605      {
 606          return IMP_SEARCH_MBOX . $this->_strip($id);
 607      }
 608  
 609      /**
 610       * Return the base search fields.
 611       *
 612       * @return array  The base search fields.
 613       */
 614      function searchFields()
 615      {
 616          return array(
 617              'from' => array(
 618                  'label' => _("From"),
 619                  'type' => IMP_SEARCH_HEADER
 620              ),
 621              'to' => array(
 622                  'label' => _("To"),
 623                  'type' => IMP_SEARCH_HEADER
 624              ),
 625              'cc' => array(
 626                  'label' => _("Cc"),
 627                  'type' => IMP_SEARCH_HEADER
 628              ),
 629              'bcc' => array(
 630                  'label' => _("Bcc"),
 631                  'type' => IMP_SEARCH_HEADER
 632              ),
 633              'subject' => array(
 634                  'label' => _("Subject"),
 635                  'type' => IMP_SEARCH_HEADER
 636              ),
 637              'body' => array(
 638                 'label' => _("Body"),
 639                 'type' => IMP_SEARCH_BODY
 640              ),
 641              'text' => array(
 642                 'label' => _("Entire Message"),
 643                 'type' => IMP_SEARCH_TEXT
 644              ),
 645              'received_on' => array(
 646                  'label' => _("Received On"),
 647                  'type' => IMP_SEARCH_DATE
 648              ),
 649              'received_until' => array(
 650                  'label' => _("Received Until"),
 651                  'type' => IMP_SEARCH_DATE
 652              ),
 653              'received_since' => array(
 654                  'label' => _("Received Since"),
 655                  'type' => IMP_SEARCH_DATE
 656              )
 657          );
 658      }
 659  
 660      /**
 661       * Update IMAP_Tree object.
 662       *
 663       * @access private
 664       *
 665       * @param string $action  Either 'delete' or 'add'.
 666       * @param string $id      The query ID to update.
 667       * @param string $label   If $action = 'add', the label to use for the
 668       *                        query ID.
 669       */
 670      function _updateIMPTree($action, $id, $label = null)
 671      {
 672          if (empty($this->_imptree)) {
 673              require_once  IMP_BASE . '/lib/IMAP/Tree.php';
 674              $this->_imptree = &IMP_Tree::singleton();
 675          }
 676  
 677          switch ($action) {
 678          case 'delete':
 679              $this->_imptree->delete($id);
 680              break;
 681  
 682          case 'add':
 683              $this->_imptree->insertVFolders(array($id => $label));
 684              break;
 685          }
 686      }
 687  
 688  }


Généré le : Thu Nov 29 12:30:07 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics