Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 39 |
|
0.00% |
0 / 5 |
CRAP | |
0.00% |
0 / 1 |
CaighdeanWebService | |
0.00% |
0 / 39 |
|
0.00% |
0 / 5 |
182 | |
0.00% |
0 / 1 |
getType | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
mapCode | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
doPairs | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 | |||
getQuery | |
0.00% |
0 / 15 |
|
0.00% |
0 / 1 |
20 | |||
parseResponse | |
0.00% |
0 / 17 |
|
0.00% |
0 / 1 |
42 |
1 | <?php |
2 | declare( strict_types = 1 ); |
3 | |
4 | namespace MediaWiki\Extension\Translate\WebService; |
5 | |
6 | use MediaWiki\Json\FormatJson; |
7 | |
8 | /** |
9 | * Implements support Caighdean translator api. |
10 | * @author Niklas Laxström |
11 | * @license GPL-2.0-or-later |
12 | * @ingroup TranslationWebService |
13 | * @since 2017.04 |
14 | * @see https://github.com/kscanne/caighdean/blob/master/API.md |
15 | */ |
16 | class CaighdeanWebService extends TranslationWebService { |
17 | /** @inheritDoc */ |
18 | public function getType(): string { |
19 | return 'mt'; |
20 | } |
21 | |
22 | /** @inheritDoc */ |
23 | protected function mapCode( string $code ): string { |
24 | return $code; |
25 | } |
26 | |
27 | /** @inheritDoc */ |
28 | protected function doPairs(): array { |
29 | $pairs = [ |
30 | 'gd' => [ 'ga' => true ], |
31 | 'gv' => [ 'ga' => true ], |
32 | ]; |
33 | |
34 | return $pairs; |
35 | } |
36 | |
37 | /** @inheritDoc */ |
38 | protected function getQuery( string $text, string $sourceLanguage, string $targetLanguage ): TranslationQuery { |
39 | if ( !isset( $this->config['url'] ) ) { |
40 | throw new TranslationWebServiceConfigurationException( '`url` not set in configuration' ); |
41 | } |
42 | |
43 | $text = trim( $text ); |
44 | if ( $text === '' ) { |
45 | throw new TranslationWebServiceInvalidInputException( 'Input is empty' ); |
46 | } |
47 | |
48 | $data = wfArrayToCgi( [ |
49 | 'foinse' => $sourceLanguage, |
50 | 'teacs' => $text, |
51 | ] ); |
52 | |
53 | // Maximum payload is 16 KiB. Based ont testing 16000 bytes is safe by leaving 224 |
54 | // bytes for other things. |
55 | if ( strlen( $data ) > 16000 ) { |
56 | throw new TranslationWebServiceInvalidInputException( 'Input is over 16000 bytes long' ); |
57 | } |
58 | |
59 | return TranslationQuery::factory( $this->config['url'] ) |
60 | ->timeout( intval( $this->config['timeout'] ) ) |
61 | ->postWithData( $data ) |
62 | ->attachProcessingInstructions( $text ); |
63 | } |
64 | |
65 | /** @inheritDoc */ |
66 | protected function parseResponse( TranslationQueryResponse $reply ): string { |
67 | $body = $reply->getBody(); |
68 | $response = FormatJson::decode( $body ); |
69 | if ( !is_array( $response ) ) { |
70 | throw new TranslationWebServiceException( 'Invalid json: ' . serialize( $body ) ); |
71 | } |
72 | |
73 | $text = ''; |
74 | $originalText = $reply->getQuery()->getProcessingInstructions(); |
75 | foreach ( $response as [ $sourceToken, $targetToken ] ) { |
76 | $separator = ' '; |
77 | $pos = strpos( $originalText, $sourceToken ); |
78 | // Try to keep the effects local. If we fail to match at token, we could accidentally |
79 | // scan very far ahead in the text, find a false match and not find matches for all |
80 | // of the tokens in the between. |
81 | if ( $pos !== false && $pos < 50 ) { |
82 | // Remove the portion of text we have processed. $pos should be zero, unless |
83 | // we failed to match something earlier. |
84 | $originalText = substr( $originalText, $pos + strlen( $sourceToken ) ); |
85 | if ( preg_match( '/^\s+/', $originalText, $match ) ) { |
86 | $separator = $match[ 0 ]; |
87 | $originalText = substr( $originalText, strlen( $separator ) ); |
88 | } else { |
89 | $separator = ''; |
90 | } |
91 | } |
92 | |
93 | $text .= $targetToken . $separator; |
94 | } |
95 | |
96 | return $text; |
97 | } |
98 | } |