Translate extension for MediaWiki
 
Loading...
Searching...
No Matches
CrossLanguageTranslationSearchQuery.php
1<?php
2
9 protected $server;
11 protected $params;
13 protected $resultset;
15 protected $total = 0;
16 protected $hl = [ '', '' ];
17
18 public function __construct( array $params, SearchableTTMServer $server ) {
19 $this->params = $params;
20 $this->server = $server;
21 }
22
23 public function getDocuments() {
24 $documents = [];
25 $offset = $this->params['offset'];
26 $limit = $this->params['limit'];
27
28 $options = $this->params;
29 $options['language'] = $this->params['sourcelanguage'];
30 // Use a bigger limit that what was requested, since we are likely to throw away many
31 // results in the local filtering step at extractMessages
32 $options['limit'] = $limit * 10;
33 // TODO: the real offset should be communicated to the frontend. It currently assumes
34 // next offset is current offset + limit and previous one is current offset - limit.
35 // It might be difficult to fix scrolling results backwards. For now we handle offset
36 // locally.
37 $options['offset'] = 0;
38
39 // @phan-suppress-next-line PhanUndeclaredMethod
40 $search = $this->server->createSearch( $this->params['query'], $options, $this->hl );
41 $scroll = $search->scroll( '5s' );
42
43 // Used for aggregations. Only the first scroll response has them.
44 $this->resultset = null;
45
46 foreach ( $scroll as $resultSet ) {
47 if ( !$this->resultset ) {
48 $this->resultset = $resultSet;
49 $this->total = $resultSet->getTotalHits();
50 }
51
52 $results = $this->extractMessages( $resultSet->getDocuments() );
53 $documents = array_merge( $documents, $results );
54
55 $count = count( $documents );
56
57 if ( $count >= $offset + $limit ) {
58 break;
59 }
60 }
61
62 if ( !$this->resultset ) {
63 // No hits for documents, just set the result set.
64 $this->resultset = $scroll->current();
65 $this->total = $scroll->current()->getTotalHits();
66 }
67
68 // clear was introduced in Elastica 5.3.1, but Elastica extension uses 5.3.0
69 if ( is_callable( [ $scroll, 'clear' ] ) ) {
70 $scroll->clear();
71 }
72 $documents = array_slice( $documents, $offset, $limit );
73
74 return $documents;
75 }
76
85 protected function extractMessages( $documents ) {
86 $messages = $ret = [];
87
88 $language = $this->params['language'];
89 foreach ( $documents as $document ) {
90 $data = $document->getData();
91
92 // @phan-suppress-next-line PhanUndeclaredMethod
93 if ( !$this->server->isLocalSuggestion( $data ) ) {
94 continue;
95 }
96
97 $title = Title::newFromText( $data['localid'] );
98 if ( !$title ) {
99 continue;
100 }
101
102 $handle = new MessageHandle( $title );
103 if ( !$handle->isValid() ) {
104 continue;
105 }
106
107 $key = $title->getNamespace() . ':' . $title->getDBkey();
108 $messages[$key] = $data['content'];
109 }
110
111 $definitions = new MessageDefinitions( $messages );
112 $collection = MessageCollection::newFromDefinitions( $definitions, $language );
113
114 $filter = $this->params['filter'];
115 if ( $filter === 'untranslated' ) {
116 $collection->filter( 'hastranslation', true );
117 } elseif ( in_array( $filter, $this->getAvailableFilters() ) ) {
118 $collection->filter( $filter, false );
119 }
120
121 if ( $filter === 'translated' || $filter === 'fuzzy' ) {
122 $collection->loadTranslations();
123 }
124
125 foreach ( $collection->keys() as $mkey => $titleValue ) {
126 $title = Title::newFromLinkTarget( $titleValue );
127
128 $result = [];
129 $result['content'] = $messages[$mkey];
130 if ( $filter === 'translated' || $filter === 'fuzzy' ) {
131 $result['content'] = $collection[$mkey]->translation();
132 }
133 $handle = new MessageHandle( $title );
134 $result['localid'] = $handle->getTitleForBase()->getPrefixedText();
135 $result['language'] = $language;
136
137 $ret[] = $result;
138 }
139
140 return $ret;
141 }
142
144 public function getAvailableFilters() {
145 return [
146 'translated',
147 'fuzzy',
148 'untranslated'
149 ];
150 }
151
152 public function getTotalHits() {
153 return $this->total;
154 }
155
156 public function getResultSet() {
157 return $this->resultset;
158 }
159}
extractMessages( $documents)
Extract messages from the documents and build message definitions.
Wrapper for message definitions, just to beauty the code.
Class for pointing to messages, like Title class is for titles.
Interface for TTMServer that can act as backend for translation search.
getTotalHits( $resultset)