Exemplo n.º 1
0
 /**
  * Executes a search against the full text index.
  *
  * @param string $searchQuery Text to search for
  * @param boolean $titleOnly If true, only searches text in titles
  * @param array $processedConstraints Structured constraints
  * @param array $orderParts Structured ordered by parts
  * @param string $groupByDiscussionType If grouping, content type of grouped results
  * @param integer $maxResults
  * @param XenForo_Search_DataHandler_Abstract $typeHandler Type-specific handler, for joins
  *
  * @return array Search results ([] => array(content type, id))
  */
 public function executeSearch($searchQuery, $titleOnly, array $processedConstraints, array $orderParts, $groupByDiscussionType, $maxResults, XenForo_Search_DataHandler_Abstract $typeHandler = null)
 {
     $db = $this->_getDb();
     $queryParts = $this->tokenizeQuery($searchQuery);
     $searchQuery = $this->parseTokenizedQuery($queryParts, $processedConstraints);
     if ($titleOnly) {
         $matchFields = 'search_index.title, search_index.metadata';
     } else {
         $matchFields = 'search_index.title, search_index.message, search_index.metadata';
     }
     $tables = array();
     $whereClauses = array();
     foreach ($processedConstraints as $constraint) {
         if (isset($constraint['query']) && !isset($constraint['metadata'])) {
             // pull queries without metadata alternatives
             list($queryTable, $queryField, $queryOperator, $queryValues) = $constraint['query'];
             if (is_array($queryValues) && count($queryValues) == 0) {
                 continue;
             }
             if ($queryOperator == '=' && is_array($queryValues)) {
                 $whereClauses[] = "{$queryTable}.{$queryField} IN (" . $db->quote($queryValues) . ")";
             } else {
                 if (!is_scalar($queryValues)) {
                     $queryValues = strval($queryValues);
                 }
                 $whereClauses[] = "{$queryTable}.{$queryField} {$queryOperator} " . $db->quote($queryValues);
             }
             $tables[] = $queryTable;
         }
     }
     $orderFields = array();
     foreach ($orderParts as $order) {
         list($orderTable, $orderField, $orderDirection) = $order;
         $orderFields[] = "{$orderTable}.{$orderField} {$orderDirection}";
         $tables[] = $orderTable;
     }
     $orderClause = $orderFields ? 'ORDER BY ' . implode(', ', $orderFields) : 'ORDER BY NULL';
     $tables = array_flip($tables);
     unset($tables['search_index']);
     if ($typeHandler) {
         $joinStructures = $typeHandler->getJoinStructures($tables);
         $joins = array();
         foreach ($joinStructures as $tableAlias => $joinStructure) {
             list($relationshipTable, $relationshipField) = $joinStructure['relationship'];
             $joins[] = "INNER JOIN {$joinStructure['table']} AS {$tableAlias} ON\n\t\t\t\t\t({$tableAlias}.{$joinStructure['key']} = {$relationshipTable}.{$relationshipField})";
         }
     } else {
         $joins = array();
     }
     $extraWhere = $whereClauses ? 'AND (' . implode(') AND (', $whereClauses) . ')' : '';
     if ($groupByDiscussionType) {
         $selectFields = $db->quote($groupByDiscussionType) . ' AS content_type, search_index.discussion_id AS content_id';
         $groupByClause = 'GROUP BY search_index.discussion_id';
     } else {
         $selectFields = 'search_index.content_type, search_index.content_id';
         $groupByClause = '';
     }
     if ($maxResults < 1) {
         $maxResults = 100;
     }
     $maxResults = intval($maxResults);
     if ($this->_searcher && $this->_searcher->hasErrors()) {
         return array();
     }
     return $db->fetchAll("\n\t\t\tSELECT {$selectFields}\n\t\t\tFROM xf_search_index AS search_index\n\t\t\t" . implode("\n", $joins) . "\n\t\t\tWHERE MATCH({$matchFields}) AGAINST (? IN BOOLEAN MODE)\n\t\t\t\t{$extraWhere}\n\t\t\t{$groupByClause}\n\t\t\t{$orderClause}\n\t\t\tLIMIT {$maxResults}\n\t\t", $searchQuery, Zend_Db::FETCH_NUM);
 }