123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- <?php
- /**
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- */
- /**
- * API module to enumerate language information.
- *
- * @ingroup API
- */
- class ApiQueryLanguageinfo extends ApiQueryBase {
- /**
- * The maximum time for {@link execute()};
- * if execution takes longer than this, apply continuation.
- *
- * If the localization cache is used, this time is not expected to ever be
- * exceeded; on the other hand, if it is not used, a typical request will
- * not yield more than a handful of languages before the time is exceeded
- * and continuation is applied, if one of the expensive props is requested.
- *
- * @var float
- */
- const MAX_EXECUTE_SECONDS = 2.0;
- /** @var callable|null */
- private $microtimeFunction;
- /**
- * @param ApiQuery $queryModule
- * @param string $moduleName
- * @param callable|null $microtimeFunction Function to use instead of microtime(), for testing.
- * Should accept no arguments and return float seconds. (null means real microtime().)
- */
- public function __construct(
- ApiQuery $queryModule,
- $moduleName,
- $microtimeFunction = null
- ) {
- parent::__construct( $queryModule, $moduleName, 'li' );
- $this->microtimeFunction = $microtimeFunction;
- }
- /** @return float */
- private function microtime() {
- if ( $this->microtimeFunction ) {
- return ( $this->microtimeFunction )();
- } else {
- return microtime( true );
- }
- }
- public function execute() {
- $endTime = $this->microtime() + self::MAX_EXECUTE_SECONDS;
- $props = array_flip( $this->getParameter( 'prop' ) );
- $includeCode = isset( $props['code'] );
- $includeBcp47 = isset( $props['bcp47'] );
- $includeDir = isset( $props['dir'] );
- $includeAutonym = isset( $props['autonym'] );
- $includeName = isset( $props['name'] );
- $includeFallbacks = isset( $props['fallbacks'] );
- $includeVariants = isset( $props['variants'] );
- $targetLanguageCode = $this->getLanguage()->getCode();
- $include = 'all';
- $availableLanguageCodes = array_keys( Language::fetchLanguageNames(
- // MediaWiki and extensions may return different sets of language codes
- // when asked for language names in different languages;
- // asking for English language names is most likely to give us the full set,
- // even though we may not need those at all
- 'en',
- $include
- ) );
- $selectedLanguageCodes = $this->getParameter( 'code' );
- if ( $selectedLanguageCodes === [ '*' ] ) {
- $languageCodes = $availableLanguageCodes;
- } else {
- $languageCodes = array_values( array_intersect(
- $availableLanguageCodes,
- $selectedLanguageCodes
- ) );
- $unrecognizedCodes = array_values( array_diff(
- $selectedLanguageCodes,
- $availableLanguageCodes
- ) );
- if ( $unrecognizedCodes !== [] ) {
- $this->addWarning( [
- 'apiwarn-unrecognizedvalues',
- $this->encodeParamName( 'code' ),
- Message::listParam( $unrecognizedCodes, 'comma' ),
- count( $unrecognizedCodes ),
- ] );
- }
- }
- // order of $languageCodes is guaranteed by Language::fetchLanguageNames()
- // and preserved by array_values() + array_intersect()
- $continue = $this->getParameter( 'continue' );
- if ( $continue === null ) {
- $continue = reset( $languageCodes );
- }
- $result = $this->getResult();
- $rootPath = [
- $this->getQuery()->getModuleName(),
- $this->getModuleName(),
- ];
- $result->addArrayType( $rootPath, 'assoc' );
- foreach ( $languageCodes as $languageCode ) {
- if ( $languageCode < $continue ) {
- continue;
- }
- $now = $this->microtime();
- if ( $now >= $endTime ) {
- $this->setContinueEnumParameter( 'continue', $languageCode );
- break;
- }
- $info = [];
- ApiResult::setArrayType( $info, 'assoc' );
- if ( $includeCode ) {
- $info['code'] = $languageCode;
- }
- if ( $includeBcp47 ) {
- $bcp47 = LanguageCode::bcp47( $languageCode );
- $info['bcp47'] = $bcp47;
- }
- if ( $includeDir ) {
- $dir = Language::factory( $languageCode )->getDir();
- $info['dir'] = $dir;
- }
- if ( $includeAutonym ) {
- $autonym = Language::fetchLanguageName(
- $languageCode,
- Language::AS_AUTONYMS,
- $include
- );
- $info['autonym'] = $autonym;
- }
- if ( $includeName ) {
- $name = Language::fetchLanguageName(
- $languageCode,
- $targetLanguageCode,
- $include
- );
- $info['name'] = $name;
- }
- if ( $includeFallbacks ) {
- $fallbacks = Language::getFallbacksFor(
- $languageCode,
- // allow users to distinguish between implicit and explicit 'en' fallbacks
- Language::STRICT_FALLBACKS
- );
- ApiResult::setIndexedTagName( $fallbacks, 'fb' );
- $info['fallbacks'] = $fallbacks;
- }
- if ( $includeVariants ) {
- $variants = Language::factory( $languageCode )->getVariants();
- ApiResult::setIndexedTagName( $variants, 'var' );
- $info['variants'] = $variants;
- }
- $fit = $result->addValue( $rootPath, $languageCode, $info );
- if ( !$fit ) {
- $this->setContinueEnumParameter( 'continue', $languageCode );
- break;
- }
- }
- }
- public function getCacheMode( $params ) {
- return 'public';
- }
- public function getAllowedParams() {
- return [
- 'prop' => [
- self::PARAM_DFLT => 'code',
- self::PARAM_ISMULTI => true,
- self::PARAM_TYPE => [
- 'code',
- 'bcp47',
- 'dir',
- 'autonym',
- 'name',
- 'fallbacks',
- 'variants',
- ],
- self::PARAM_HELP_MSG_PER_VALUE => [],
- ],
- 'code' => [
- self::PARAM_DFLT => '*',
- self::PARAM_ISMULTI => true,
- ],
- 'continue' => [
- self::PARAM_HELP_MSG => 'api-help-param-continue',
- ],
- ];
- }
- protected function getExamplesMessages() {
- $pathUrl = 'action=' . $this->getQuery()->getModuleName() .
- '&meta=' . $this->getModuleName();
- $pathMsg = $this->getModulePath();
- $prefix = $this->getModulePrefix();
- return [
- "$pathUrl"
- => "apihelp-$pathMsg-example-simple",
- "$pathUrl&{$prefix}prop=autonym|name&uselang=de"
- => "apihelp-$pathMsg-example-autonym-name-de",
- "$pathUrl&{$prefix}prop=fallbacks|variants&{$prefix}code=oc"
- => "apihelp-$pathMsg-example-fallbacks-variants-oc",
- "$pathUrl&{$prefix}prop=bcp47|dir"
- => "apihelp-$pathMsg-example-bcp47-dir",
- ];
- }
- }
|