Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 76
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
TranslationAidsActionApi
0.00% covered (danger)
0.00%
0 / 76
0.00% covered (danger)
0.00%
0 / 3
240
0.00% covered (danger)
0.00%
0 / 1
 execute
0.00% covered (danger)
0.00%
0 / 57
0.00% covered (danger)
0.00%
0 / 1
182
 getAllowedParams
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
2
 getExamplesMessages
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2declare( strict_types = 1 );
3
4namespace MediaWiki\Extension\Translate\TranslatorInterface\Aid;
5
6use ApiBase;
7use MediaWiki\Extension\Translate\MessageGroupProcessing\MessageGroups;
8use MediaWiki\Extension\Translate\MessageLoading\MessageHandle;
9use MediaWiki\Extension\Translate\TranslatorInterface\TranslationHelperException;
10use MediaWiki\Extension\Translate\WebService\QueryAggregator;
11use MediaWiki\Extension\Translate\WebService\QueryAggregatorAware;
12use MediaWiki\Logger\LoggerFactory;
13use MediaWiki\Title\Title;
14use Wikimedia\ParamValidator\ParamValidator;
15
16/**
17 * Api module for querying message aids.
18 * @author Niklas Laxström
19 * @license GPL-2.0-or-later
20 * @ingroup API TranslateAPI
21 */
22class TranslationAidsActionApi extends ApiBase {
23    public function execute() {
24        $params = $this->extractRequestParams();
25
26        $title = Title::newFromText( $params['title'] );
27        if ( !$title ) {
28            $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $params['title'] ) ] );
29        }
30
31        $handle = new MessageHandle( $title );
32        if ( !$handle->isValid() ) {
33            $this->dieWithError( 'apierror-translate-nomessagefortitle', 'nomessagefortitle' );
34        }
35
36        if ( (string)$params['group'] !== '' ) {
37            $group = MessageGroups::getGroup( $params['group'] );
38        } else {
39            $group = $handle->getGroup();
40        }
41
42        if ( !$group ) {
43            $this->dieWithError( 'apierror-translate-invalidgroup', 'invalidgroup' );
44        }
45
46        $data = [];
47        $times = [];
48
49        $props = $params['prop'];
50        $aggregator = new QueryAggregator();
51
52        // Figure out the intersection of supported and requested aids
53        $types = TranslationAid::getTypes();
54        $props = array_intersect( $props, array_keys( $types ) );
55
56        $result = $this->getResult();
57
58        // Create list of aids, populate web services queries
59        /** @var TranslationAid[] $aids */
60        $aids = [];
61
62        $dataProvider = new TranslationAidDataProvider( $handle );
63
64        // Message definition should not be empty, but sometimes is.
65        // See: https://phabricator.wikimedia.org/T285830
66        // Identify and log.
67        if ( !$dataProvider->hasDefinition() ) {
68            LoggerFactory::getInstance( 'Translate' )->warning(
69                'Message definition is empty! Title: {title}, group: {group}, key: {key}',
70                [
71                    'title' => $handle->getTitle()->getPrefixedText(),
72                    'group' => $group->getId(),
73                    'key' => $handle->getKey()
74                ]
75            );
76        }
77
78        foreach ( $props as $type ) {
79            // Do not proceed if translation aid is not supported for this message group
80            if ( !isset( $types[$type] ) ) {
81                $types[$type] = UnsupportedTranslationAid::class;
82            }
83
84            $class = $types[$type];
85            $obj = new $class( $group, $handle, $this, $dataProvider );
86
87            if ( $obj instanceof QueryAggregatorAware ) {
88                $obj->setQueryAggregator( $aggregator );
89                try {
90                    $obj->populateQueries();
91                } catch ( TranslationHelperException $e ) {
92                    $data[$type] = [ 'error' => $e->getMessage() ];
93                    // Prevent processing this aids and thus overwriting our error
94                    continue;
95                }
96            }
97
98            $aids[$type] = $obj;
99        }
100
101        // Execute all web service queries asynchronously to save time
102        $start = microtime( true );
103        $aggregator->run();
104        $times['query_aggregator'] = round( microtime( true ) - $start, 3 );
105
106        // Construct the result data structure
107        foreach ( $aids as $type => $obj ) {
108            $start = microtime( true );
109
110            try {
111                $aid = $obj->getData();
112            } catch ( TranslationHelperException $e ) {
113                $aid = [ 'error' => $e->getMessage() ];
114            }
115
116            if ( isset( $aid['**'] ) ) {
117                $result->setIndexedTagName( $aid, $aid['**'] );
118                unset( $aid['**'] );
119            }
120
121            $data[$type] = $aid;
122            $times[$type] = round( microtime( true ) - $start, 3 );
123        }
124
125        $result->addValue( null, 'helpers', $data );
126        $result->addValue( null, 'times', $times );
127    }
128
129    protected function getAllowedParams(): array {
130        $props = array_keys( TranslationAid::getTypes() );
131
132        return [
133            'title' => [
134                ParamValidator::PARAM_TYPE => 'string',
135                ParamValidator::PARAM_REQUIRED => true,
136            ],
137            'group' => [
138                ParamValidator::PARAM_TYPE => 'string',
139            ],
140            'prop' => [
141                ParamValidator::PARAM_DEFAULT => implode( '|', $props ),
142                ParamValidator::PARAM_TYPE => $props,
143                ParamValidator::PARAM_ISMULTI => true,
144            ],
145        ];
146    }
147
148    protected function getExamplesMessages() {
149        return [
150            'action=translationaids&title=MediaWiki:January/fi'
151                => 'apihelp-translationaids-example-1',
152        ];
153    }
154}