diff options
Diffstat (limited to 'www/wiki/extensions/Translate/api/ApiQueryMessageCollection.php')
-rw-r--r-- | www/wiki/extensions/Translate/api/ApiQueryMessageCollection.php | 279 |
1 files changed, 279 insertions, 0 deletions
diff --git a/www/wiki/extensions/Translate/api/ApiQueryMessageCollection.php b/www/wiki/extensions/Translate/api/ApiQueryMessageCollection.php new file mode 100644 index 00000000..f9353d62 --- /dev/null +++ b/www/wiki/extensions/Translate/api/ApiQueryMessageCollection.php @@ -0,0 +1,279 @@ +<?php +/** + * Api module for querying MessageCollection. + * + * @file + * @author Niklas Laxström + * @license GPL-2.0-or-later + */ + +/** + * Api module for querying MessageCollection. + * + * @ingroup API TranslateAPI + */ +class ApiQueryMessageCollection extends ApiQueryGeneratorBase { + + public function __construct( $query, $moduleName ) { + parent::__construct( $query, $moduleName, 'mc' ); + } + + public function execute() { + $this->run(); + } + + public function getCacheMode( $params ) { + return 'public'; + } + + public function executeGenerator( $resultPageSet ) { + $this->run( $resultPageSet ); + } + + private function validateLanguageCode( $code ) { + if ( !Language::isValidBuiltInCode( $code ) ) { + $this->dieWithError( [ 'apierror-translate-invalidlanguage' ] ); + } + } + + private function run( ApiPageSet $resultPageSet = null ) { + global $wgTranslateBlacklist; + + $params = $this->extractRequestParams(); + + $group = MessageGroups::getGroup( $params['group'] ); + if ( !$group ) { + $this->dieWithError( [ 'apierror-missingparam', 'mcgroup' ] ); + } + + $languageCode = $params[ 'language' ]; + $this->validateLanguageCode( $languageCode ); + if ( $group->getSourceLanguage() === $languageCode ) { + $name = Language::fetchLanguageName( $languageCode, $this->getLanguage()->getCode() ); + $this->addWarning( [ 'apiwarn-translate-language-disabled-source', wfEscapeWikiText( $name ) ] ); + } + $languages = $group->getTranslatableLanguages(); + if ( $languages !== null ) { + if ( !isset( $languages[ $languageCode ] ) ) { + $name = Language::fetchLanguageName( $languageCode, $this->getLanguage()->getCode() ); + $this->dieWithError( [ 'apierror-translate-language-disabled', $name ] ); + } + } else { + $checks = [ + $group->getId(), + strtok( $group->getId(), '-' ), + '*' + ]; + + foreach ( $checks as $check ) { + if ( isset( $wgTranslateBlacklist[ $check ][ $languageCode ] ) ) { + $name = Language::fetchLanguageName( $languageCode, $this->getLanguage()->getCode() ); + $reason = $wgTranslateBlacklist[ $check ][ $languageCode ]; + $this->dieWithError( [ 'apierror-translate-language-disabled-reason', $name, $reason ] ); + } + } + } + + if ( MessageGroups::isDynamic( $group ) ) { + /** + * @var RecentMessageGroup $group + */ + $group->setLanguage( $params['language'] ); + } + + $messages = $group->initCollection( $params['language'] ); + + foreach ( $params['filter'] as $filter ) { + $value = null; + if ( strpos( $filter, ':' ) !== false ) { + list( $filter, $value ) = explode( ':', $filter, 2 ); + } + /* The filtering params here are swapped wrt MessageCollection. + * There (fuzzy) means do not show fuzzy, which is the same as !fuzzy + * here and fuzzy here means (fuzzy, false) there. */ + try { + if ( $filter[0] === '!' ) { + $messages->filter( substr( $filter, 1 ), true, $value ); + } else { + $messages->filter( $filter, false, $value ); + } + } catch ( MWException $e ) { + $this->dieWithError( + [ 'apierror-translate-invalidfilter', wfEscapeWikiText( $e->getMessage() ) ], + 'invalidfilter' + ); + } + } + + $resultSize = count( $messages ); + $offsets = $messages->slice( $params['offset'], $params['limit'] ); + $batchSize = count( $messages ); + list( /*$backwardsOffset*/, $forwardsOffset, $startOffset ) = $offsets; + + $result = $this->getResult(); + $result->addValue( + [ 'query', 'metadata' ], + 'state', + self::getWorkflowState( $group->getId(), $params['language'] ) + ); + + $result->addValue( [ 'query', 'metadata' ], 'resultsize', $resultSize ); + $result->addValue( + [ 'query', 'metadata' ], + 'remaining', + $resultSize - $startOffset - $batchSize + ); + + $messages->loadTranslations(); + + $pages = []; + + if ( $forwardsOffset !== false ) { + $this->setContinueEnumParameter( 'offset', $forwardsOffset ); + } + + $props = array_flip( $params['prop'] ); + + /** @var Title $title */ + foreach ( $messages->keys() as $mkey => $title ) { + if ( is_null( $resultPageSet ) ) { + $data = $this->extractMessageData( $result, $props, $messages[$mkey] ); + $data['title'] = $title->getPrefixedText(); + $handle = new MessageHandle( $title ); + + if ( $handle->isValid() ) { + $data['primaryGroup'] = $handle->getGroup()->getId(); + } + + $result->addValue( [ 'query', $this->getModuleName() ], null, $data ); + } else { + $pages[] = $title; + } + } + + if ( is_null( $resultPageSet ) ) { + $result->addIndexedTagName( + [ 'query', $this->getModuleName() ], + 'message' + ); + } else { + $resultPageSet->populateFromTitles( $pages ); + } + } + + /** + * @param ApiResult $result + * @param array $props + * @param ThinMessage $message + * @return array + */ + public function extractMessageData( $result, $props, $message ) { + $data['key'] = $message->key(); + + if ( isset( $props['definition'] ) ) { + $data['definition'] = $message->definition(); + } + if ( isset( $props['translation'] ) ) { + // Remove !!FUZZY!! from translation if present. + $translation = $message->translation(); + if ( $translation !== null ) { + $translation = str_replace( TRANSLATE_FUZZY, '', $translation ); + } + $data['translation'] = $translation; + } + if ( isset( $props['tags'] ) ) { + $data['tags'] = $message->getTags(); + $result->setIndexedTagName( $data['tags'], 'tag' ); + } + // BC + if ( isset( $props['revision'] ) ) { + $data['revision'] = $message->getProperty( 'revision' ); + } + if ( isset( $props['properties'] ) ) { + foreach ( $message->getPropertyNames() as $prop ) { + $data['properties'][$prop] = $message->getProperty( $prop ); + ApiResult::setIndexedTagNameRecursive( $data['properties'], 'val' ); + } + } + + return $data; + } + + /** + * Get the current workflow state for the message group for the given language + * + * @param string $groupId Group id. + * @param string $language Language tag. + * @return string|bool State id or false. + */ + protected static function getWorkflowState( $groupId, $language ) { + $dbr = wfGetDB( DB_REPLICA ); + + return $dbr->selectField( + 'translate_groupreviews', + 'tgr_state', + [ + 'tgr_group' => $groupId, + 'tgr_lang' => $language + ], + __METHOD__ + ); + } + + public function getAllowedParams() { + return [ + 'group' => [ + ApiBase::PARAM_TYPE => 'string', + ApiBase::PARAM_REQUIRED => true, + ], + 'language' => [ + ApiBase::PARAM_TYPE => 'string', + ApiBase::PARAM_DFLT => 'en', + ], + 'limit' => [ + ApiBase::PARAM_DFLT => 500, + ApiBase::PARAM_TYPE => 'limit', + ApiBase::PARAM_MIN => 1, + ApiBase::PARAM_MAX => ApiBase::LIMIT_BIG2, + ApiBase::PARAM_MAX2 => ApiBase::LIMIT_BIG2, + ], + 'offset' => [ + ApiBase::PARAM_DFLT => '', + ApiBase::PARAM_TYPE => 'string', + ApiBase::PARAM_HELP_MSG => 'api-help-param-continue', + ], + 'filter' => [ + ApiBase::PARAM_TYPE => 'string', + ApiBase::PARAM_DFLT => '!optional|!ignored', + ApiBase::PARAM_ISMULTI => true, + ], + 'prop' => [ + ApiBase::PARAM_TYPE => [ + 'definition', + 'translation', + 'tags', + 'revision', + 'properties' + ], + ApiBase::PARAM_DFLT => 'definition|translation', + ApiBase::PARAM_ISMULTI => true, + ApiBase::PARAM_HELP_MSG => + [ 'apihelp-query+messagecollection-param-prop', '!!FUZZY!!' ], + ], + ]; + } + + protected function getExamplesMessages() { + return [ + 'action=query&meta=siteinfo&siprop=languages' + => 'apihelp-query+messagecollection-example-1', + 'action=query&list=messagecollection&mcgroup=page-Example' + => 'apihelp-query+messagecollection-example-2', + 'action=query&list=messagecollection&mcgroup=page-Example&mclanguage=fi&' . + 'mcprop=definition|translation|tags&mcfilter=optional' + => 'apihelp-query+messagecollection-example-3', + 'action=query&generator=messagecollection&gmcgroup=page-Example&gmclanguage=nl&prop=revisions' + => 'apihelp-query+messagecollection-example-4', + ]; + } +} |