/**
  * getInstance()
  *
  * Connect to the backend engine and store for later use
  *
  * @static
  * @return SugarSearchEngineInterface
  */
 public static function getInstance($name = '', $config = array(), $useDefaultWhenFTSDown = false)
 {
     require_once 'include/SugarSearchEngine/SugarSearchEngineAbstractBase.php';
     if ($useDefaultWhenFTSDown && SugarSearchEngineAbstractBase::isSearchEngineDown()) {
         $name = 'SugarSearchEngine';
     }
     if (!isset(self::$_instance[$name])) {
         self::$_instance[$name] = self::setupEngine($name, $config);
     }
     return self::$_instance[$name];
 }
 public function __construct($params = array())
 {
     // Setup Elastica Client object
     $this->_config = $params;
     // this timeout can be overriden at $sugar_config['full_text_engine']['Elastic']['timeout']
     if (empty($this->_config['timeout'])) {
         $this->_config['timeout'] = 15;
     }
     $this->setClient(new \Elastica\Client($this->_config));
     // Setup index strategy
     $this->indexStrategy = SugarSearchEngineElasticIndexStrategyFactory::getinstance();
     // Asynchronous indexing through fts_queue table
     $this->forceAsyncIndex = SugarConfig::getInstance()->get('search_engine.force_async_index', false);
     // Elastic mapping
     $mappingClass = SugarAutoLoader::customClass('SugarSearchEngineElasticMapping');
     $this->mapper = new $mappingClass($this);
     // Facet handler
     $this->facetHandler = new FacetHandler();
     parent::__construct();
 }
 /**
  * This function is used to hand off the global search to the FTS Search Emgine
  * @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.
  */
 protected function globalSearchFullText(ServiceBase $api, array $args, SugarSearchEngineAbstractBase $searchEngine, array $options)
 {
     $options['append_wildcard'] = 1;
     if (empty($options['moduleList'])) {
         require_once 'modules/ACL/ACLController.php';
         $moduleList = SugarSearchEngineMetadataHelper::getSystemEnabledFTSModules();
         // filter based on User Access if Blank
         $ACL = new ACLController();
         // moduleList is passed by reference
         $ACL->filterModuleList($moduleList);
         $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)) {
                 foreach ($existingfields as $field) {
                     if (empty($seed->field_defs[$field]['full_text_search'])) {
                         continue;
                     }
                     $prefix = $seed->module_name;
                     if (!isset($seed->field_defs[$field]['source']) || $seed->field_defs[$field]['source'] != 'non-db') {
                         $customWhere[] = "{$prefix}.{$field}";
                     }
                 }
             }
         }
         $options['searchFields'] = $customWhere;
     }
     $options['moduleFilter'] = $options['moduleList'];
     $results = $searchEngine->search($options['query'], $options['offset'], $options['limit'], $options);
     $returnedRecords = array();
     $total = 0;
     $api->action = 'list';
     if (is_object($results)) {
         foreach ($results as $result) {
             $record = BeanFactory::retrieveBean($result->getModule(), $result->getId());
             // if we can't get the bean skip it
             if (!$record) {
                 continue;
             }
             $module = $record->module_dir;
             // 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();
                 }
             }
             if (!empty($moduleFields) && !in_array('id', $moduleFields)) {
                 $moduleFields[] = 'id';
             }
             $moduleArgs['fields'] = implode(',', $moduleFields);
             $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'] = $result->getScore();
             //Add highlighted text
             $formattedRecord['_search']['highlighted'] = $result->getHighlightedHitText();
             $returnedRecords[] = $formattedRecord;
         }
         $total = $results->getTotalHits();
     }
     if ($total > $options['limit'] + $options['offset']) {
         $nextOffset = $options['offset'] + $options['limit'];
     } else {
         $nextOffset = -1;
     }
     return array('next_offset' => $nextOffset, 'records' => $returnedRecords);
 }
    sugar_die("silentFTSIndex.php is CLI only.\n");
}
if (empty($current_language)) {
    $current_language = $sugar_config['default_language'];
}
$app_list_strings = return_app_list_strings_language($current_language);
$app_strings = return_application_language($current_language);
global $current_user;
$current_user = BeanFactory::getBean('Users');
$current_user->getSystemUser();
// Pop off the filename
array_shift($argv);
// Don't wipe the index if we're just doing individual modules
$clearData = empty($argv);
// Allows for php -f silentFTSIndex.php Bugs Cases
$modules = $argv;
require_once 'include/SugarSearchEngine/SugarSearchEngineFullIndexer.php';
require_once 'include/SugarSearchEngine/SugarSearchEngineAbstractBase.php';
try {
    SugarSearchEngineAbstractBase::markSearchEngineStatus(false);
    // set search engine to "up"
    $indexer = new SugarSearchEngineFullIndexer();
    if (!$indexer->performFullSystemIndex($modules, $clearData)) {
        echo "FTS index failed. Please check the sugarcrm.log for more details.\n";
        exit(1);
    }
} catch (Exception $e) {
    echo "Exception: " . $e->getMessage() . "\n";
    exit(1);
}
exit(0);
 /**
  * This method sets the full text search to available when a scheduled FTS Index occurs.  
  * An indexing can only occur with a valid connection
  * 
  * TODO: XXX Fix this to use admin settings not config options
  * @return bool
  */
 protected function setFTSUp()
 {
     $cfg = new Configurator();
     $cfg->config['fts_disable_notification'] = false;
     $cfg->handleOverride();
     // set it up
     SugarSearchEngineAbstractBase::markSearchEngineStatus(false);
     $admin = BeanFactory::newBean('Administration');
     $admin->retrieveSettings(FALSE, TRUE);
     return TRUE;
 }
 /**
  * Check FTS server status and update cache file and notification.
  *
  * @return boolean
  */
 protected function updateFTSServerStatus()
 {
     $GLOBALS['log']->debug('Going to check and update FTS Server status.');
     // check FTS server status
     $result = $this->SSEngine->getServerStatus();
     if ($result['valid']) {
         $GLOBALS['log']->debug('FTS Server is OK.');
         // server is ok
         if (SugarSearchEngineAbstractBase::isSearchEngineDown()) {
             $GLOBALS['log']->debug('Restoring FTS Server status.');
             // mark fts server as up
             SugarSearchEngineAbstractBase::markSearchEngineStatus(false);
             // remove notification
             $cfg = new Configurator();
             $cfg->config['fts_disable_notification'] = false;
             $cfg->handleOverride();
         }
         return true;
     } else {
         $GLOBALS['log']->info('FTS Server is down?');
         // server is down
         if (!SugarSearchEngineAbstractBase::isSearchEngineDown()) {
             $GLOBALS['log']->fatal('Marking FTS Server as down.');
             // fts is not marked as down, so mark it as down
             SugarSearchEngineAbstractBase::markSearchEngineStatus(true);
         }
         return false;
     }
 }