Translate extension for MediaWiki
 
Loading...
Searching...
No Matches
SearchTranslationsActionApi.php
1<?php
2declare( strict_types = 1 );
3
4namespace MediaWiki\Extension\Translate\TtmServer;
5
6use MediaWiki\Api\ApiBase;
7use MediaWiki\Api\ApiMain;
8use MediaWiki\Config\Config;
9use MediaWiki\Config\ServiceOptions;
11use MediaWiki\Logger\LoggerFactory;
12use Wikimedia\ParamValidator\ParamValidator;
13use Wikimedia\ParamValidator\TypeDef\IntegerDef;
14
19class SearchTranslationsActionApi extends ApiBase {
20
22 private $options;
23
24 private const CONSTRUCTOR_OPTIONS = [
25 'LanguageCode',
26 'TranslateTranslationDefaultService',
27 'TranslateTranslationServices',
28 ];
29
30 public function __construct(
31 ApiMain $main,
32 string $moduleName,
33 Config $config,
34 private readonly TtmServerFactory $ttmServerFactory,
35 ) {
36 parent::__construct( $main, $moduleName );
37 $this->options = new ServiceOptions( self::CONSTRUCTOR_OPTIONS, $config );
38 }
39
40 public function execute(): void {
41 if ( !$this->getSearchableTtmServers() ) {
42 $this->dieWithError( 'apierror-translate-notranslationservices' );
43 }
44
45 $params = $this->extractRequestParams();
46
47 $server = $this->ttmServerFactory->create( $params[ 'service' ] );
48 if ( !$server instanceof SearchableTtmServer ) {
49 $this->dieWithError( 'apierror-translate-notranslationservices' );
50 }
51
52 $result = $this->getResult();
53
54 try {
55 if ( $params['filter'] !== '' ) {
56 $translationSearch = new CrossLanguageTranslationSearchQuery( $params, $server );
57 $documents = $translationSearch->getDocuments();
58 $total = $translationSearch->getTotalHits();
59 } else {
60 $searchResults = $server->search(
61 $params['query'],
62 $params,
63 [ '', '' ]
64 );
65 $documents = $server->getDocuments( $searchResults );
66 $total = $server->getTotalHits( $searchResults );
67 }
68 } catch ( TtmServerException $e ) {
70 LoggerFactory::getInstance( LogNames::MAIN )->warning(
71 'Translation search server failed: {exception}',
72 [ 'exception' => $e ]
73 );
74 $this->dieWithError( 'tux-sst-search-backend-error' );
75 }
76 // unexpected issue, let it bubble up
77 throw $e;
78 }
79 $result->addValue( [ 'search', 'metadata' ], 'total', $total );
80 $result->addValue( 'search', 'translations', $documents );
81 }
82
84 private function getSearchableTtmServers(): array {
85 $ttmServiceIds = $this->ttmServerFactory->getNames();
86
87 $good = [];
88 foreach ( $ttmServiceIds as $serviceId ) {
89 $ttmServer = $this->ttmServerFactory->create( $serviceId );
90 if ( $ttmServer instanceof SearchableTtmServer ) {
91 $good[] = $serviceId;
92 }
93 }
94
95 return $good;
96 }
97
98 protected function getAllowedFilters(): array {
99 return [
100 '',
101 'translated',
102 'fuzzy',
103 'untranslated'
104 ];
105 }
106
107 protected function getAllowedParams(): array {
108 $available = $this->getSearchableTtmServers();
109
110 $filters = $this->getAllowedFilters();
111
112 $ret = [
113 'service' => [
114 ParamValidator::PARAM_TYPE => $available,
115 ],
116 'query' => [
117 ParamValidator::PARAM_TYPE => 'string',
118 ParamValidator::PARAM_REQUIRED => true,
119 ],
120 'sourcelanguage' => [
121 ParamValidator::PARAM_TYPE => 'string',
122 ParamValidator::PARAM_DEFAULT => $this->options->get( 'LanguageCode' ),
123 ],
124 'language' => [
125 ParamValidator::PARAM_TYPE => 'string',
126 ParamValidator::PARAM_DEFAULT => '',
127 ],
128 'group' => [
129 ParamValidator::PARAM_TYPE => 'string',
130 ParamValidator::PARAM_DEFAULT => '',
131 ],
132 'filter' => [
133 ParamValidator::PARAM_TYPE => $filters,
134 ParamValidator::PARAM_DEFAULT => '',
135 ],
136 'match' => [
137 ParamValidator::PARAM_TYPE => 'string',
138 ParamValidator::PARAM_DEFAULT => '',
139 ],
140 'case' => [
141 ParamValidator::PARAM_TYPE => 'string',
142 ParamValidator::PARAM_DEFAULT => '0',
143 ],
144 'offset' => [
145 ParamValidator::PARAM_TYPE => 'integer',
146 ParamValidator::PARAM_DEFAULT => 0,
147 ],
148 'limit' => [
149 ParamValidator::PARAM_DEFAULT => 25,
150 ParamValidator::PARAM_TYPE => 'limit',
151 IntegerDef::PARAM_MIN => 1,
152 IntegerDef::PARAM_MAX => ApiBase::LIMIT_SML1,
153 IntegerDef::PARAM_MAX2 => ApiBase::LIMIT_SML2
154 ],
155 ];
156
157 if ( $available ) {
158 // Don't add this if no services are available, it makes
159 // ApiStructureTest unhappy
160 $ret['service'][ParamValidator::PARAM_DEFAULT] =
161 $this->options->get( 'TranslateTranslationDefaultService' );
162 }
163
164 return $ret;
165 }
166
167 protected function getExamplesMessages(): array {
168 return [
169 'action=searchtranslations&language=fr&query=aide'
170 => 'apihelp-searchtranslations-example-1',
171 'action=searchtranslations&language=fr&query=edit&filter=untranslated'
172 => 'apihelp-searchtranslations-example-2',
173 ];
174 }
175}
Constants for log channel names used in this extension.
Definition LogNames.php:13
const MAIN
Default log channel for the extension.
Definition LogNames.php:15
API module for search translations @license GPL-2.0-or-later.
Class to handle TtmServer specific exceptions.
const TRANSIENT_SEARCH_BACKEND_FAILURE
Exception code for transient errors when contacting the search backend.
Interface for TtmServer that can act as backend for translation search.