public function getData()
 {
     $suggestions = array();
     $text = $this->getDefinition();
     $from = $this->group->getSourceLanguage();
     $to = $this->handle->getCode();
     // "Local" queries using a client can't be run in parallel with web services
     global $wgTranslateTranslationServices;
     foreach ($wgTranslateTranslationServices as $name => $config) {
         $server = TTMServer::factory($config);
         try {
             if ($server instanceof ReadableTTMServer) {
                 // Except if they are public, we can call back via API
                 if (isset($config['public']) && $config['public'] === true) {
                     continue;
                 }
                 $query = $server->query($from, $to, $text);
             } else {
                 continue;
             }
         } catch (Exception $e) {
             // Not ideal to catch all exceptions
             continue;
         }
         foreach ($query as $item) {
             $item['service'] = $name;
             $item['source_language'] = $from;
             $item['local'] = $server->isLocalSuggestion($item);
             $item['uri'] = $server->expandLocation($item);
             $suggestions[] = $item;
         }
     }
     // Results from web services
     foreach ($this->getQueryData() as $queryData) {
         $sugs = $this->formatSuggestions($queryData);
         $suggestions = array_merge($suggestions, $sugs);
     }
     $suggestions = TTMServer::sortSuggestions($suggestions);
     // Must be here to not mess up the sorting function
     $suggestions['**'] = 'suggestion';
     return $suggestions;
 }
 protected function processQueryResults($res, $text, $targetLanguage)
 {
     $timeLimit = microtime(true) + 5;
     $lenA = mb_strlen($text);
     $results = array();
     foreach ($res as $row) {
         if (microtime(true) > $timeLimit) {
             // Having no suggestions is better than preventing translation
             // altogether by timing out the request :(
             break;
         }
         $a = $text;
         $b = $row->tms_text;
         $lenB = mb_strlen($b);
         $len = min($lenA, $lenB);
         if ($len > 600) {
             // two strings of length 1500 ~ 10s
             // two strings of length 2250 ~ 30s
             $dist = $len;
         } else {
             $dist = self::levenshtein($a, $b, $lenA, $lenB);
         }
         $quality = 1 - $dist * 0.9 / $len;
         if ($quality >= $this->config['cutoff']) {
             $results[] = array('source' => $row->tms_text, 'target' => $row->tmt_text, 'context' => $row->tms_context, 'location' => $row->tms_context . '/' . $targetLanguage, 'quality' => $quality, 'wiki' => isset($row->tms_wiki) ? $row->tms_wiki : wfWikiId());
         }
     }
     $results = TTMServer::sortSuggestions($results);
     return $results;
 }