Ejemplo n.º 1
0
 /**
  * This function is used to hand off the global search to the built-in SugarSearchEngine (aka SugarSpot)
  * @param $api ServiceBase The API class of the request
  * @param $args array The arguments array passed in from the API
  * @param $searchEngine SugarSearchEngine The SugarSpot search engine created using the Factory in the caller
  * @param $options array An array of options to pass through to the search engine, they get translated to the $searchOptions array so you can see exactly what gets passed through
  * @return array Two elements, 'records' the list of returned records formatted through FormatBean, and 'next_offset' which will indicate to the user if there are additional records to be returned.
  */
 public function globalSearchSpot(ServiceBase $api, array $args, $searchEngine, array $options)
 {
     require_once 'modules/Home/UnifiedSearchAdvanced.php';
     $searchOptions = array('modules' => $options['moduleList'], 'current_module' => $options['primaryModule'], 'return_beans' => true, 'my_items' => $options['my_items'], 'favorites' => $options['favorites'], 'orderBy' => $options['orderBy'], 'fields' => $options['fieldFilters'], 'selectFields' => $options['selectFields'], 'limitPerModule' => $options['limitPerModule'], 'allowEmptySearch' => true, 'distinct' => 'DISTINCT', 'return_beans' => true);
     if (isset($options['deleted'])) {
         $searchOptions['deleted'] = $options['deleted'];
     }
     $multiModule = false;
     if (empty($options['moduleList']) || count($options['moduleList']) == 0 || count($options['moduleList']) > 1) {
         $multiModule = true;
     }
     if (empty($options['moduleList'])) {
         require_once 'modules/ACL/ACLController.php';
         $usa = new UnifiedSearchAdvanced();
         $moduleList = $usa->getUnifiedSearchModules();
         // get the module names [array keys]
         $moduleList = array_keys($moduleList);
         // filter based on User Access if Blank
         $ACL = new ACLController();
         // moduleList is passed by reference
         $ACL->filterModuleList($moduleList);
         $searchOptions['modules'] = $options['moduleList'] = $moduleList;
     }
     if (!empty($options['searchFields'])) {
         $customWhere = array();
         foreach ($options['moduleList'] as $module) {
             $seed = BeanFactory::getBean($module);
             $fields = array_keys($seed->field_defs);
             $existingfields = array_intersect($fields, $options['searchFields']);
             if (!empty($existingfields)) {
                 $customTable = $seed->get_custom_table_name();
                 $table = $seed->table_name;
                 foreach ($existingfields as $field) {
                     if (!isset($seed->field_defs[$field]['unified_search']) || $seed->field_defs[$field]['unified_search'] !== true) {
                         continue;
                     }
                     $prefix = $table;
                     if (isset($GLOBALS['dictionary'][$seed->object_name]['custom_fields'][$field])) {
                         $prefix = $customTable;
                     }
                     if (!isset($seed->field_defs[$field]['source']) || $seed->field_defs[$field]['source'] != 'non-db') {
                         $customWhere[$module][] = "{$prefix}.{$field} LIKE '{$options['query']}%'";
                     }
                 }
                 if (isset($customWhere[$module])) {
                     $searchOptions['custom_where_module'][$module] = '(' . implode(' OR ', $customWhere[$module]) . ')';
                 }
             }
         }
     }
     $offset = $options['offset'];
     // One for luck.
     // Well, actually it's so that we know that there are additional results
     $limit = $options['limit'] + 1;
     if ($multiModule && $options['offset'] != 0) {
         // With more than one module, there is no way to do offsets for real, so we have to fake it.
         $limit = $limit + $offset;
         $offset = 0;
     }
     if (!$multiModule) {
         // It's not multi-module, the per-module limit should be the same as the master limit
         $searchOptions['limitPerModule'] = $limit;
     }
     if (isset($options['custom_select'])) {
         $searchOptions['custom_select'] = $options['custom_select'];
     }
     if (isset($options['custom_from'])) {
         $searchOptions['custom_from'] = $options['custom_from'];
     }
     if (isset($options['custom_where'])) {
         $searchOptions['custom_where'] = $options['custom_where'];
     }
     $results = $searchEngine->search($options['query'], $offset, $limit, $searchOptions);
     $returnedRecords = array();
     $api->action = 'list';
     foreach ($results as $module => $moduleResults) {
         if (!is_array($moduleResults['data'])) {
             continue;
         }
         $moduleArgs = $args;
         // Need to override the filter arg so that it looks like something formatBean expects
         if (!empty($options['fieldFilters'][$module])) {
             $moduleFields = $options['fieldFilters'][$module];
         } else {
             if (!empty($options['fieldFilters']['_default'])) {
                 $moduleFields = $options['fieldFilters']['_default'];
             } else {
                 $moduleFields = array();
             }
         }
         $moduleArgs['fields'] = implode(',', $moduleFields);
         foreach ($moduleResults['data'] as $record) {
             $formattedRecord = $this->formatBean($api, $moduleArgs, $record);
             $formattedRecord['_module'] = $module;
             // The SQL based search engine doesn't know how to score records, so set it to 1
             $formattedRecord['_search']['score'] = 1.0;
             $returnedRecords[] = $formattedRecord;
         }
     }
     if ($multiModule) {
         // Need to re-sort the results because the DB search engine clumps them together per-module
         $this->resultSetSortData = $options['orderByArray'];
         usort($returnedRecords, array($this, 'resultSetSort'));
     }
     if ($multiModule && $options['offset'] != 0) {
         // The merged module mess leaves us in a bit of a pickle with offsets and limits
         if (count($returnedRecords) > $options['offset'] + $options['limit']) {
             $nextOffset = $options['offset'] + $options['limit'];
         } else {
             $nextOffset = -1;
         }
         $returnedRecords = array_slice($returnedRecords, $options['offset'], $options['limit']);
     } else {
         // Otherwise, offsets and limits should work.
         if (count($returnedRecords) > $options['limit']) {
             $nextOffset = $options['offset'] + $options['limit'];
         } else {
             $nextOffset = -1;
         }
         $returnedRecords = array_slice($returnedRecords, 0, $options['limit']);
     }
     if ($options['offset'] === 'end') {
         $nextOffset = -1;
     }
     return array('next_offset' => $nextOffset, 'records' => $returnedRecords);
 }