* Update QUnit from v1.14.0 to v1.16.0.
* Update Moment.js from v2.8.3 to v2.8.4.
* Special:Tags now allows for manipulating the list of user-modifiable change
- tags. Actually modifying the tagging of a revision or log entry is not
- implemented yet.
+ tags.
* Added 'managetags' user right and 'ChangeTagCanCreate', 'ChangeTagCanDelete',
and 'ChangeTagCanCreate' hooks to allow for managing user-modifiable change
tags.
proper, published library, which is now tagged as v1.0.0.
* A new message (defaulting to blank), 'editnotice-notext', can be shown to users
when they are editing if no edit notices apply to the page being edited.
+* (T94536) You can now make the sitenotice appear to logged-in users only by
+ editing MediaWiki:Anonnotice and replacing its content with "". Setting it to
+ "-" (default) will continue disable it and fallback to MediaWiki:Sitenotice.
+* Modifying the tagging of a revision or log entry is now available via
+ Special:EditTags, generally accessed via the revision-deletion-like interface
+ on history pages and Special:Log is likely to be more useful.
+* Added 'applychangetags' and 'changetags' user rights.
==== External libraries ====
* MediaWiki now requires certain external libraries to be installed. In the past
HTML validation.
* $wgUseTidy is now set when parserTests are run with the tidy option to match
output on wiki.
+* (T37472) update.php will purge ResourceLoader cache unless --nopurge is passed to it.
=== Action API changes in 1.25 ===
* (T67403) XML tag highlighting is now only performed for formats
Title::userCan() via the API.
* Default type param for query list=watchlist and list=recentchanges has
been changed from all types (e.g. including 'external') to 'edit|new|log'.
+ * Added formatversion to format=json, still experimental.
=== Action API internal changes in 1.25 ===
* ApiHelp has been rewritten to support i18n and paginated HTML output.
the current request was sent with the 'callback' parameter (or any future
method that breaks the same-origin policy).
* Profiling methods in ApiBase are deprecated and no longer need to be called.
+ * ApiResult was greatly overhauled. See inline documentation for details.
+ * ApiResult will automatically convert objects to strings or arrays (depending
+ on whether a __toString() method exists on the object), and will refuse to
+ add unsupported value types.
+ * An informal interface, ApiSerializable, exists to override the default
+ object conversion.
+ * ApiResult/ApiFormatBase "raw mode" is deprecated.
+ * ApiFormatXml now assumes defaults and so on instead of throwing errors when
+ metadata isn't set.
* The following methods have been deprecated and may be removed in a future
release:
* ApiBase::getDescription
* ApiBase::profileDBIn
* ApiBase::profileDBOut
* ApiBase::getProfileDBTime
+ * ApiBase::getResultData
* ApiFormatBase::setUnescapeAmps
* ApiFormatBase::getWantsHelp
* ApiFormatBase::setHelp
* ApiFormatBase::formatHTML
* ApiFormatBase::setBufferResult
* ApiFormatBase::getDescription
+ * ApiFormatBase::getNeedsRawData
* ApiMain::setHelp
* ApiMain::reallyMakeHelpMsg
* ApiMain::makeHelpMsgHeader
+ * ApiResult::setRawMode
+ * ApiResult::getIsRawMode
+ * ApiResult::getData
+ * ApiResult::setElement
+ * ApiResult::setContent
+ * ApiResult::setIndexedTagName_recursive
+ * ApiResult::setIndexedTagName_internal
+ * ApiResult::setParsedLimit
+ * ApiResult::beginContinuation
+ * ApiResult::setContinueParam
+ * ApiResult::setGeneratorContinueParam
+ * ApiResult::endContinuation
+ * ApiResult::size
+ * ApiResult::convertStatusToArray
* ApiQueryImageInfo::getPropertyDescriptions
* The following classes have been deprecated and may be removed in a future
release:
retrievedfrom, thisisdeleted, viewsourcelink, lastmodifiedat, laggedslavemode,
protect-summary-cascade
* All BloomCache related code has been removed. This was largely experimental.
+* $wgResourceModuleSkinStyles no longer supports per-module local or remote paths. They
+ can only be set for the entire skin.
+* Removed global function swap(). (deprecated since 1.24)
+* The global importScript and importStylesheet functions, as well as the loadedScripts object,
+ from wikibits.js (deprecated since 1.17) now emit warnings through mw.log.warn when accessed.
== Compatibility ==
'ApiCheckToken' => __DIR__ . '/includes/api/ApiCheckToken.php',
'ApiClearHasMsg' => __DIR__ . '/includes/api/ApiClearHasMsg.php',
'ApiComparePages' => __DIR__ . '/includes/api/ApiComparePages.php',
+ 'ApiContinuationManager' => __DIR__ . '/includes/api/ApiContinuationManager.php',
'ApiCreateAccount' => __DIR__ . '/includes/api/ApiCreateAccount.php',
'ApiDelete' => __DIR__ . '/includes/api/ApiDelete.php',
'ApiDisabled' => __DIR__ . '/includes/api/ApiDisabled.php',
'ApiEditPage' => __DIR__ . '/includes/api/ApiEditPage.php',
'ApiEmailUser' => __DIR__ . '/includes/api/ApiEmailUser.php',
+ 'ApiErrorFormatter' => __DIR__ . '/includes/api/ApiErrorFormatter.php',
+ 'ApiErrorFormatter_BackCompat' => __DIR__ . '/includes/api/ApiErrorFormatter.php',
'ApiExpandTemplates' => __DIR__ . '/includes/api/ApiExpandTemplates.php',
'ApiFeedContributions' => __DIR__ . '/includes/api/ApiFeedContributions.php',
'ApiFeedRecentChanges' => __DIR__ . '/includes/api/ApiFeedRecentChanges.php',
'ApiLogout' => __DIR__ . '/includes/api/ApiLogout.php',
'ApiMain' => __DIR__ . '/includes/api/ApiMain.php',
'ApiManageTags' => __DIR__ . '/includes/api/ApiManageTags.php',
+ 'ApiMessage' => __DIR__ . '/includes/api/ApiMessage.php',
'ApiModuleManager' => __DIR__ . '/includes/api/ApiModuleManager.php',
'ApiMove' => __DIR__ . '/includes/api/ApiMove.php',
'ApiOpenSearch' => __DIR__ . '/includes/api/ApiOpenSearch.php',
'ApiQueryUsers' => __DIR__ . '/includes/api/ApiQueryUsers.php',
'ApiQueryWatchlist' => __DIR__ . '/includes/api/ApiQueryWatchlist.php',
'ApiQueryWatchlistRaw' => __DIR__ . '/includes/api/ApiQueryWatchlistRaw.php',
+ 'ApiRawMessage' => __DIR__ . '/includes/api/ApiMessage.php',
'ApiResult' => __DIR__ . '/includes/api/ApiResult.php',
'ApiRevisionDelete' => __DIR__ . '/includes/api/ApiRevisionDelete.php',
'ApiRollback' => __DIR__ . '/includes/api/ApiRollback.php',
'ApiRsd' => __DIR__ . '/includes/api/ApiRsd.php',
+ 'ApiSerializable' => __DIR__ . '/includes/api/ApiSerializable.php',
'ApiSetNotificationTimestamp' => __DIR__ . '/includes/api/ApiSetNotificationTimestamp.php',
'ApiStashEdit' => __DIR__ . '/includes/api/ApiStashEdit.php',
+ 'ApiTag' => __DIR__ . '/includes/api/ApiTag.php',
'ApiTokens' => __DIR__ . '/includes/api/ApiTokens.php',
'ApiUnblock' => __DIR__ . '/includes/api/ApiUnblock.php',
'ApiUndelete' => __DIR__ . '/includes/api/ApiUndelete.php',
'CgzCopyTransaction' => __DIR__ . '/maintenance/storage/recompressTracked.php',
'ChangePassword' => __DIR__ . '/maintenance/changePassword.php',
'ChangeTags' => __DIR__ . '/includes/ChangeTags.php',
+ 'ChangeTagsList' => __DIR__ . '/includes/changetags/ChangeTagsList.php',
+ 'ChangeTagsLogItem' => __DIR__ . '/includes/changetags/ChangeTagsLogItem.php',
+ 'ChangeTagsLogList' => __DIR__ . '/includes/changetags/ChangeTagsLogList.php',
+ 'ChangeTagsRevisionItem' => __DIR__ . '/includes/changetags/ChangeTagsRevisionItem.php',
+ 'ChangeTagsRevisionList' => __DIR__ . '/includes/changetags/ChangeTagsRevisionList.php',
'ChangesFeed' => __DIR__ . '/includes/changes/ChangesFeed.php',
'ChangesList' => __DIR__ . '/includes/changes/ChangesList.php',
'ChangesListSpecialPage' => __DIR__ . '/includes/specialpage/ChangesListSpecialPage.php',
'Http' => __DIR__ . '/includes/HttpFunctions.php',
'HttpError' => __DIR__ . '/includes/exception/HttpError.php',
'HttpStatus' => __DIR__ . '/includes/libs/HttpStatus.php',
+ 'IApiMessage' => __DIR__ . '/includes/api/ApiMessage.php',
'ICacheHelper' => __DIR__ . '/includes/cache/CacheHelper.php',
'IContextSource' => __DIR__ . '/includes/context/IContextSource.php',
'IDBAccessObject' => __DIR__ . '/includes/dao/IDBAccessObject.php',
'MWLoggerFactory' => __DIR__ . '/includes/debug/logger/Shims.php',
'MWLoggerLegacyLogger' => __DIR__ . '/includes/debug/logger/Shims.php',
'MWLoggerLegacySpi' => __DIR__ . '/includes/debug/logger/Shims.php',
- 'MWLoggerMonologHandler' => __DIR__ . '/includes/debug/logger/Shims.php',
- 'MWLoggerMonologLegacyFormatter' => __DIR__ . '/includes/debug/logger/Shims.php',
- 'MWLoggerMonologProcessor' => __DIR__ . '/includes/debug/logger/Shims.php',
- 'MWLoggerMonologSpi' => __DIR__ . '/includes/debug/logger/Shims.php',
- 'MWLoggerMonologSyslogHandler' => __DIR__ . '/includes/debug/logger/Shims.php',
+ 'MWLoggerMonologHandler' => __DIR__ . '/includes/debug/logger/monolog/Shims.php',
+ 'MWLoggerMonologLegacyFormatter' => __DIR__ . '/includes/debug/logger/monolog/Shims.php',
+ 'MWLoggerMonologProcessor' => __DIR__ . '/includes/debug/logger/monolog/Shims.php',
+ 'MWLoggerMonologSpi' => __DIR__ . '/includes/debug/logger/monolog/Shims.php',
+ 'MWLoggerMonologSyslogHandler' => __DIR__ . '/includes/debug/logger/monolog/Shims.php',
'MWLoggerNullSpi' => __DIR__ . '/includes/debug/logger/Shims.php',
'MWLoggerSpi' => __DIR__ . '/includes/debug/logger/Shims.php',
'MWMemcached' => __DIR__ . '/includes/objectcache/MemcachedClient.php',
'PoolCounter_Stub' => __DIR__ . '/includes/poolcounter/PoolCounter.php',
'PoolWorkArticleView' => __DIR__ . '/includes/poolcounter/PoolWorkArticleView.php',
'PopulateBacklinkNamespace' => __DIR__ . '/maintenance/populateBacklinkNamespace.php',
- 'PopulateBloomFilter' => __DIR__ . '/maintenance/populateBloomCache.php',
'PopulateCategory' => __DIR__ . '/maintenance/populateCategory.php',
'PopulateFilearchiveSha1' => __DIR__ . '/maintenance/populateFilearchiveSha1.php',
'PopulateImageSha1' => __DIR__ . '/maintenance/populateImageSha1.php',
'SpecialContributions' => __DIR__ . '/includes/specials/SpecialContributions.php',
'SpecialCreateAccount' => __DIR__ . '/includes/specials/SpecialCreateAccount.php',
'SpecialDiff' => __DIR__ . '/includes/specials/SpecialDiff.php',
+ 'SpecialEditTags' => __DIR__ . '/includes/specials/SpecialEditTags.php',
'SpecialEditWatchlist' => __DIR__ . '/includes/specials/SpecialEditWatchlist.php',
'SpecialEmailUser' => __DIR__ . '/includes/specials/SpecialEmailuser.php',
'SpecialExpandTemplates' => __DIR__ . '/includes/specials/SpecialExpandTemplates.php',
'SpecialNewFiles' => __DIR__ . '/includes/specials/SpecialNewimages.php',
'SpecialNewpages' => __DIR__ . '/includes/specials/SpecialNewpages.php',
'SpecialPage' => __DIR__ . '/includes/specialpage/SpecialPage.php',
+ 'SpecialPageAction' => __DIR__ . '/includes/actions/SpecialPageAction.php',
'SpecialPageFactory' => __DIR__ . '/includes/specialpage/SpecialPageFactory.php',
'SpecialPageLanguage' => __DIR__ . '/includes/specials/SpecialPageLanguage.php',
'SpecialPagesWithProp' => __DIR__ . '/includes/specials/SpecialPagesWithProp.php',
'TableCleanupTest' => __DIR__ . '/maintenance/cleanupTable.inc',
'TableDiffFormatter' => __DIR__ . '/includes/diff/TableDiffFormatter.php',
'TablePager' => __DIR__ . '/includes/pager/TablePager.php',
+ 'TagLogFormatter' => __DIR__ . '/includes/logging/TagLogFormatter.php',
'TempFSFile' => __DIR__ . '/includes/filebackend/TempFSFile.php',
'TempFileRepo' => __DIR__ . '/includes/filerepo/FileRepo.php',
'TemplateParser' => __DIR__ . '/includes/TemplateParser.php',
*/
const GET_VALUES_FOR_HELP = 1;
+ /** @var array Maps extension paths to info arrays */
+ private static $extensionInfo = null;
+
/** @var ApiMain */
private $mMainModule;
/** @var string */
private $mModuleName, $mModulePrefix;
private $mSlaveDB = null;
private $mParamCache = array();
+ /** @var array|null|bool */
+ private $mModuleSource = false;
/**
* @param ApiMain $mainModule
}
/**
- * Get the result data array (read-only)
- * @return array
+ * Get the error formatter
+ * @return ApiErrorFormatter
*/
- public function getResultData() {
- return $this->getResult()->getData();
+ public function getErrorFormatter() {
+ // Main module has getErrorFormatter() method overridden
+ // Safety - avoid infinite loop:
+ if ( $this->isMain() ) {
+ ApiBase::dieDebug( __METHOD__, 'base method was called on main module. ' );
+ }
+
+ return $this->getMain()->getErrorFormatter();
}
/**
return $this->mSlaveDB;
}
+ /**
+ * Get the continuation manager
+ * @return ApiContinuationManager|null
+ */
+ public function getContinuationManager() {
+ // Main module has getContinuationManager() method overridden
+ // Safety - avoid infinite loop:
+ if ( $this->isMain() ) {
+ ApiBase::dieDebug( __METHOD__, 'base method was called on main module. ' );
+ }
+
+ return $this->getMain()->getContinuationManager();
+ }
+
+ /**
+ * Set the continuation manager
+ * @param ApiContinuationManager|null
+ */
+ public function setContinuationManager( $manager ) {
+ // Main module has setContinuationManager() method overridden
+ // Safety - avoid infinite loop:
+ if ( $this->isMain() ) {
+ ApiBase::dieDebug( __METHOD__, 'base method was called on main module. ' );
+ }
+
+ $this->getMain()->setContinuationManager( $manager );
+ }
+
/**@}*/
/************************************************************************//**
$value = $this->getMain()->canApiHighLimits()
? $paramSettings[self::PARAM_MAX2]
: $paramSettings[self::PARAM_MAX];
- $this->getResult()->setParsedLimit( $this->getModuleName(), $value );
+ $this->getResult()->addParsedLimit( $this->getModuleName(), $value );
} else {
$value = intval( $value );
$this->validateLimit(
* @param string $warning Warning message
*/
public function setWarning( $warning ) {
- $result = $this->getResult();
- $data = $result->getData();
- $moduleName = $this->getModuleName();
- if ( isset( $data['warnings'][$moduleName] ) ) {
- // Don't add duplicate warnings
- $oldWarning = $data['warnings'][$moduleName]['*'];
- $warnPos = strpos( $oldWarning, $warning );
- // If $warning was found in $oldWarning, check if it starts at 0 or after "\n"
- if ( $warnPos !== false && ( $warnPos === 0 || $oldWarning[$warnPos - 1] === "\n" ) ) {
- // Check if $warning is followed by "\n" or the end of the $oldWarning
- $warnPos += strlen( $warning );
- if ( strlen( $oldWarning ) <= $warnPos || $oldWarning[$warnPos] === "\n" ) {
- return;
- }
- }
- // If there is a warning already, append it to the existing one
- $warning = "$oldWarning\n$warning";
- }
- $msg = array();
- ApiResult::setContent( $msg, $warning );
- $result->addValue( 'warnings', $moduleName,
- $msg, ApiResult::OVERRIDE | ApiResult::ADD_ON_TOP | ApiResult::NO_SIZE_CHECK );
+ $msg = new ApiRawMessage( $warning, 'warning' );
+ $this->getErrorFormatter()->addWarning( $this->getModuleName(), $msg );
}
/**
'code' => 'nosuchrcid',
'info' => "There is no change with rcid \"\$1\""
),
+ 'nosuchlogid' => array(
+ 'code' => 'nosuchlogid',
+ 'info' => "There is no log entry with ID \"\$1\""
+ ),
'protect-invalidaction' => array(
'code' => 'protect-invalidaction',
'info' => "Invalid protection type \"\$1\""
return $flags;
}
+ /**
+ * Returns information about the source of this module, if known
+ *
+ * Returned array is an array with the following keys:
+ * - path: Install path
+ * - name: Extension name, or "MediaWiki" for core
+ * - namemsg: (optional) i18n message key for a display name
+ * - license-name: (optional) Name of license
+ *
+ * @return array|null
+ */
+ protected function getModuleSourceInfo() {
+ global $IP;
+
+ if ( $this->mModuleSource !== false ) {
+ return $this->mModuleSource;
+ }
+
+ // First, try to find where the module comes from...
+ $rClass = new ReflectionClass( $this );
+ $path = $rClass->getFileName();
+ if ( !$path ) {
+ // No path known?
+ $this->mModuleSource = null;
+ return null;
+ }
+ $path = realpath( $path ) ?: $path;
+
+ // Build map of extension directories to extension info
+ if ( self::$extensionInfo === null ) {
+ self::$extensionInfo = array(
+ realpath( __DIR__ ) ?: __DIR__ => array(
+ 'path' => $IP,
+ 'name' => 'MediaWiki',
+ 'license-name' => 'GPL-2.0+',
+ ),
+ realpath( "$IP/extensions" ) ?: "$IP/extensions" => null,
+ );
+ $keep = array(
+ 'path' => null,
+ 'name' => null,
+ 'namemsg' => null,
+ 'license-name' => null,
+ );
+ foreach ( $this->getConfig()->get( 'ExtensionCredits' ) as $group ) {
+ foreach ( $group as $ext ) {
+ if ( !isset( $ext['path'] ) || !isset( $ext['name'] ) ) {
+ // This shouldn't happen, but does anyway.
+ continue;
+ }
+
+ $extpath = $ext['path'];
+ if ( !is_dir( $extpath ) ) {
+ $extpath = dirname( $extpath );
+ }
+ self::$extensionInfo[realpath( $extpath ) ?: $extpath] =
+ array_intersect_key( $ext, $keep );
+ }
+ }
+ foreach ( ExtensionRegistry::getInstance()->getAllThings() as $ext ) {
+ $extpath = $ext['path'];
+ if ( !is_dir( $extpath ) ) {
+ $extpath = dirname( $extpath );
+ }
+ self::$extensionInfo[realpath( $extpath ) ?: $extpath] =
+ array_intersect_key( $ext, $keep );
+ }
+ }
+
+ // Now traverse parent directories until we find a match or run out of
+ // parents.
+ do {
+ if ( array_key_exists( $path, self::$extensionInfo ) ) {
+ // Found it!
+ $this->mModuleSource = self::$extensionInfo[$path];
+ return $this->mModuleSource;
+ }
+
+ $oldpath = $path;
+ $path = dirname( $path );
+ } while ( $path !== $oldpath );
+
+ // No idea what extension this might be.
+ $this->mModuleSource = null;
+ return null;
+ }
+
/**
* Called from ApiHelp before the pieces are joined together and returned.
*
return 0;
}
+ /**
+ * Get the result data array (read-only)
+ * @deprecated since 1.25, use $this->getResult() methods instead
+ * @return array
+ */
+ public function getResultData() {
+ return $this->getResult()->getData();
+ }
+
/**@}*/
}
$titleObj = $newTitle;
}
- $apiResult->setIndexedTagName( $redirValues, 'r' );
+ ApiResult::setIndexedTagName( $redirValues, 'r' );
$apiResult->addValue( null, 'redirects', $redirValues );
// Since the page changed, update $pageObj
$requestArray['wpWatchthis'] = '';
}
+ // Apply change tags
+ if ( count( $params['tags'] ) ) {
+ if ( $user->isAllowed( 'applychangetags' ) ) {
+ $requestArray['wpChangeTags'] = implode( ',', $params['tags'] );
+ } else {
+ $this->dieUsage( 'You don\'t have permission to set change tags.', 'taggingnotallowed' );
+ }
+ }
+
// Pass through anything else we might have been given, to support extensions
// This is kind of a hack but it's the best we can do to make extensions work
$requestArray += $this->getRequest()->getValues();
case EditPage::AS_TEXTBOX_EMPTY:
$this->dieUsageMsg( 'emptynewsection' );
+ case EditPage::AS_CHANGE_TAG_ERROR:
+ $this->dieStatus( $status );
+
case EditPage::AS_SUCCESS_NEW_ARTICLE:
$r['new'] = '';
// fall-through
),
'text' => null,
'summary' => null,
+ 'tags' => array(
+ ApiBase::PARAM_TYPE => ChangeTags::listExplicitlyDefinedTags(),
+ ApiBase::PARAM_ISMULTI => true,
+ ),
'minor' => false,
'notminor' => false,
'bot' => false,
'mime' => 'text/html',
'help' => $html,
);
- $result->setSubelements( $data, 'help' );
+ ApiResult::setSubelementsList( $data, 'help' );
$result->addValue( null, $this->getModuleName(), $data );
} else {
$result->reset();
);
}
- $flags = $module->getHelpFlags();
- if ( $flags ) {
- $help['flags'] .= Html::openElement( 'div',
- array( 'class' => 'apihelp-block apihelp-flags' ) );
- $msg = $context->msg( 'api-help-flags' );
- if ( !$msg->isDisabled() ) {
- $help['flags'] .= self::wrap(
- $msg->numParams( count( $flags ) ), 'apihelp-block-head', 'div'
- );
+ $help['flags'] .= Html::openElement( 'div',
+ array( 'class' => 'apihelp-block apihelp-flags' ) );
+ $msg = $context->msg( 'api-help-flags' );
+ if ( !$msg->isDisabled() ) {
+ $help['flags'] .= self::wrap(
+ $msg->numParams( count( $flags ) ), 'apihelp-block-head', 'div'
+ );
+ }
+ $help['flags'] .= Html::openElement( 'ul' );
+ foreach ( $module->getHelpFlags() as $flag ) {
+ $help['flags'] .= Html::rawElement( 'li', null,
+ self::wrap( $context->msg( "api-help-flag-$flag" ), "apihelp-flag-$flag" )
+ );
+ }
+ $sourceInfo = $module->getModuleSourceInfo();
+ if ( $sourceInfo ) {
+ if ( isset( $sourceInfo['namemsg'] ) ) {
+ $extname = $context->msg( $sourceInfo['namemsg'] )->text();
+ } else {
+ $extname = $sourceInfo['name'];
}
- $help['flags'] .= Html::openElement( 'ul' );
- foreach ( $flags as $flag ) {
- $help['flags'] .= Html::rawElement( 'li', null,
- self::wrap( $context->msg( "api-help-flag-$flag" ), "apihelp-flag-$flag" )
- );
+ $help['flags'] .= Html::rawElement( 'li', null,
+ self::wrap(
+ $context->msg( 'api-help-source', $extname, $sourceInfo['name'] ),
+ 'apihelp-source'
+ )
+ );
+
+ $link = SpecialPage::getTitleFor( 'Version', 'License/' . $sourceInfo['name'] );
+ if ( isset( $sourceInfo['license-name'] ) ) {
+ $msg = $context->msg( 'api-help-license', $link, $sourceInfo['license-name'] );
+ } elseif ( SpecialVersion::getExtLicenseFileName( dirname( $sourceInfo['path'] ) ) ) {
+ $msg = $context->msg( 'api-help-license-noname', $link );
+ } else {
+ $msg = $context->msg( 'api-help-license-unknown' );
}
- $help['flags'] .= Html::closeElement( 'ul' );
- $help['flags'] .= Html::closeElement( 'div' );
+ $help['flags'] .= Html::rawElement( 'li', null,
+ self::wrap( $msg, 'apihelp-license' )
+ );
+ } else {
+ $help['flags'] .= Html::rawElement( 'li', null,
+ self::wrap( $context->msg( 'api-help-source-unknown' ), 'apihelp-source' )
+ );
+ $help['flags'] .= Html::rawElement( 'li', null,
+ self::wrap( $context->msg( 'api-help-license-unknown' ), 'apihelp-license' )
+ );
}
+ $help['flags'] .= Html::closeElement( 'ul' );
+ $help['flags'] .= Html::closeElement( 'div' );
foreach ( $module->getFinalDescription() as $msg ) {
$msg->setContext( $context );
'imagerotate' => 'ApiImageRotate',
'revisiondelete' => 'ApiRevisionDelete',
'managetags' => 'ApiManageTags',
+ 'tag' => 'ApiTag',
);
/**
*/
private $mPrinter;
- private $mModuleMgr, $mResult;
+ private $mModuleMgr, $mResult, $mErrorFormatter, $mContinuationManager;
private $mAction;
private $mEnableWrite;
private $mInternalMode, $mSquidMaxage, $mModule;
Hooks::run( 'ApiMain::moduleManager', array( $this->mModuleMgr ) );
- $this->mResult = new ApiResult( $this );
+ $this->mResult = new ApiResult( $this->getConfig()->get( 'APIMaxResultSize' ) );
+ $this->mErrorFormatter = new ApiErrorFormatter_BackCompat( $this->mResult );
+ $this->mResult->setErrorFormatter( $this->mErrorFormatter );
+ $this->mResult->setMainForContinuation( $this );
+ $this->mContinuationManager = null;
$this->mEnableWrite = $enableWrite;
$this->mSquidMaxage = -1; // flag for executeActionWithErrorHandling()
return $this->mResult;
}
+ /**
+ * Get the ApiErrorFormatter object associated with current request
+ * @return ApiErrorFormatter
+ */
+ public function getErrorFormatter() {
+ return $this->mErrorFormatter;
+ }
+
+ /**
+ * Get the continuation manager
+ * @return ApiContinuationManager|null
+ */
+ public function getContinuationManager() {
+ return $this->mContinuationManager;
+ }
+
+ /**
+ * Set the continuation manager
+ * @param ApiContinuationManager|null
+ */
+ public function setContinuationManager( $manager ) {
+ if ( $manager !== null ) {
+ if ( !$manager instanceof ApiContinuationManager ) {
+ throw new InvalidArgumentException( __METHOD__ . ': Was passed ' .
+ is_object( $manager ) ? get_class( $manager ) : gettype( $manager )
+ );
+ }
+ if ( $this->mContinuationManager !== null ) {
+ throw new UnexpectedValueException(
+ __METHOD__ . ': tried to set manager from ' . $manager->getSource() .
+ ' when a manager is already set from ' . $this->mContinuationManager->getSource()
+ );
+ }
+ }
+ $this->mContinuationManager = $manager;
+ }
+
/**
* Get the API module object. Only works after executeAction()
*
// Bug 63145: Rollback any open database transactions
if ( !( $e instanceof UsageException ) ) {
// UsageExceptions are intentional, so don't rollback if that's the case
- MWExceptionHandler::rollbackMasterChangesAndLog( $e );
+ try {
+ MWExceptionHandler::rollbackMasterChangesAndLog( $e );
+ } catch ( DBError $e2 ) {
+ // Rollback threw an exception too. Log it, but don't interrupt
+ // our regularly scheduled exception handling.
+ MWExceptionHandler::logException( $e2 );
+ }
}
// Allow extra cleanup and logging
// User entered incorrect parameters - generate error response
$errMessage = $e->getMessageArray();
$link = wfExpandUrl( wfScript( 'api' ) );
- ApiResult::setContent( $errMessage, "See $link for API usage" );
+ ApiResult::setContentValue( $errMessage, 'docref', "See $link for API usage" );
} else {
// Something is seriously wrong
if ( ( $e instanceof DBQueryError ) && !$config->get( 'ShowSQLErrors' ) ) {
'info' => '[' . MWExceptionHandler::getLogId( $e ) . '] ' . $info,
);
if ( $config->get( 'ShowExceptionDetails' ) ) {
- ApiResult::setContent(
+ ApiResult::setContentValue(
$errMessage,
+ 'trace',
MWExceptionHandler::getRedactedTraceAsString( $e )
);
}
}
// Remember all the warnings to re-add them later
- $oldResult = $result->getData();
- $warnings = isset( $oldResult['warnings'] ) ? $oldResult['warnings'] : null;
+ $warnings = $result->getResultData( array( 'warnings' ) );
$result->reset();
// Re-add the id
$this->setWarning( 'SECURITY WARNING: $wgDebugAPI is enabled' );
}
- $this->getResult()->cleanUpUTF8();
$printer = $this->mPrinter;
-
$printer->initPrinter( false );
$printer->execute();
$printer->closePrinter();
$result->addValue( array( $this->getModuleName() ), 'helpformat', $this->helpFormat );
foreach ( $res as $key => $stuff ) {
- $result->setIndexedTagName( $res[$key], 'module' );
+ ApiResult::setIndexedTagName( $res[$key], 'module' );
}
if ( $params['mainmodule'] ) {
}
$res[$key][] = $a;
}
- $this->getResult()->setIndexedTagName( $res[$key], 'msg' );
+ ApiResult::setIndexedTagName( $res[$key], 'msg' );
break;
}
}
}
$ret['prefix'] = $module->getModulePrefix();
+ $sourceInfo = $module->getModuleSourceInfo();
+ if ( $sourceInfo ) {
+ $ret['source'] = $sourceInfo['name'];
+ if ( isset( $sourceInfo['namemsg'] ) ) {
+ $ret['sourcename'] = $this->context->msg( $sourceInfo['namemsg'] )->text();
+ } else {
+ $ret['sourcename'] = $ret['source'];
+ }
+
+ $link = SpecialPage::getTitleFor( 'Version', 'License/' . $sourceInfo['name'] )->getFullUrl();
+ if ( isset( $sourceInfo['license-name'] ) ) {
+ $ret['licensetag'] = $sourceInfo['license-name'];
+ $ret['licenselink'] = (string)$link;
+ } elseif ( SpecialVersion::getExtLicenseFileName( dirname( $sourceInfo['path'] ) ) ) {
+ $ret['licenselink'] = (string)$link;
+ }
+ }
+
$this->formatHelpMessages( $ret, 'description', $module->getFinalDescription() );
foreach ( $module->getHelpFlags() as $flag ) {
if ( isset( $ret['helpurls'][0] ) && $ret['helpurls'][0] === false ) {
$ret['helpurls'] = array();
}
- $result->setIndexedTagName( $ret['helpurls'], 'helpurl' );
+ ApiResult::setIndexedTagName( $ret['helpurls'], 'helpurl' );
if ( $this->helpFormat !== 'none' ) {
$ret['examples'] = array();
if ( is_array( $item['description'] ) ) {
$item['description'] = $item['description'][0];
} else {
- $result->setSubelements( $item, 'description' );
+ ApiResult::setSubelementsList( $item, 'description' );
}
}
$ret['examples'][] = $item;
}
- $result->setIndexedTagName( $ret['examples'], 'example' );
+ ApiResult::setIndexedTagName( $ret['examples'], 'example' );
}
$ret['parameters'] = array();
if ( is_array( $item['type'] ) ) {
// To prevent sparse arrays from being serialized to JSON as objects
$item['type'] = array_values( $item['type'] );
- $result->setIndexedTagName( $item['type'], 't' );
+ ApiResult::setIndexedTagName( $item['type'], 't' );
}
}
if ( isset( $settings[ApiBase::PARAM_MAX] ) ) {
);
if ( count( $i ) ) {
$info['values'] = $i;
- $result->setIndexedTagName( $info['values'], 'v' );
+ ApiResult::setIndexedTagName( $info['values'], 'v' );
}
$this->formatHelpMessages( $info, 'text', array(
$this->context->msg( "apihelp-{$path}-paraminfo-{$tag}" )
->params( $this->context->getLanguage()->commaList( $i ) )
->params( $module->getModulePrefix() )
) );
- $result->setSubelements( $info, 'text' );
+ ApiResult::setSubelementsList( $info, 'text' );
$item['info'][] = $info;
}
- $result->setIndexedTagName( $item['info'], 'i' );
+ ApiResult::setIndexedTagName( $item['info'], 'i' );
}
$ret['parameters'][] = $item;
}
- $result->setIndexedTagName( $ret['parameters'], 'param' );
+ ApiResult::setIndexedTagName( $ret['parameters'], 'param' );
return $ret;
}
$popts = $this->makeParserOptions( $pageObj, $params );
// If for some reason the "oldid" is actually the current revision, it may be cached
- if ( $rev->isCurrent() ) {
+ // Deliberately comparing $pageObj->getLatest() with $rev->getId(), rather than
+ // checking $rev->isCurrent(), because $pageObj is what actually ends up being used,
+ // and if its ->getLatest() is outdated, $rev->isCurrent() won't tell us that.
+ if ( $rev->getId() == $pageObj->getLatest() ) {
// May get from/save to parser cache
$p_result = $this->getParsedContent( $pageObj, $popts,
$pageid, isset( $prop['wikitext'] ) );
} else { // Not $oldid, but $pageid or $page
if ( $params['redirects'] ) {
$reqParams = array(
- 'action' => 'query',
'redirects' => '',
);
if ( !is_null( $pageid ) ) {
}
$req = new FauxRequest( $reqParams );
$main = new ApiMain( $req );
- $main->execute();
- $data = $main->getResultData();
- $redirValues = isset( $data['query']['redirects'] )
- ? $data['query']['redirects']
- : array();
+ $pageSet = new ApiPageSet( $main );
+ $pageSet->execute();
+
$to = $page;
- foreach ( (array)$redirValues as $r ) {
- $to = $r['to'];
+ foreach ( $pageSet->getRedirectTitles() as $title ) {
+ $to = $title->getFullText();
}
$pageParams = array( 'title' => $to );
} elseif ( !is_null( $pageid ) ) {
// Build a result and bail out
$result_array = array();
$result_array['text'] = array();
- ApiResult::setContent( $result_array['text'], $this->pstContent->serialize( $format ) );
+ ApiResult::setContentValue( $result_array['text'], 'text', $this->pstContent->serialize( $format ) );
if ( isset( $prop['wikitext'] ) ) {
$result_array['wikitext'] = array();
- ApiResult::setContent( $result_array['wikitext'], $this->content->serialize( $format ) );
+ ApiResult::setContentValue( $result_array['wikitext'], 'wikitext', $this->content->serialize( $format ) );
}
if ( !is_null( $params['summary'] ) ||
( !is_null( $params['sectiontitle'] ) && $this->section === 'new' )
) {
$result_array['parsedsummary'] = array();
- ApiResult::setContent( $result_array['parsedsummary'], $this->formatSummary( $titleObj, $params ) );
+ ApiResult::setContentValue(
+ $result_array['parsedsummary'],
+ 'parsedsummary',
+ $this->formatSummary( $titleObj, $params )
+ );
}
$result->addValue( null, $this->getModuleName(), $result_array );
if ( isset( $prop['text'] ) ) {
$result_array['text'] = array();
- ApiResult::setContent( $result_array['text'], $p_result->getText() );
+ ApiResult::setContentValue( $result_array['text'], 'text', $p_result->getText() );
}
if ( !is_null( $params['summary'] ) ||
( !is_null( $params['sectiontitle'] ) && $this->section === 'new' )
) {
$result_array['parsedsummary'] = array();
- ApiResult::setContent( $result_array['parsedsummary'], $this->formatSummary( $titleObj, $params ) );
+ ApiResult::setContentValue(
+ $result_array['parsedsummary'],
+ 'parsedsummary',
+ $this->formatSummary( $titleObj, $params )
+ );
}
if ( isset( $prop['langlinks'] ) ) {
if ( isset( $prop['categorieshtml'] ) ) {
$categoriesHtml = $this->categoriesHtml( $p_result->getCategories() );
$result_array['categorieshtml'] = array();
- ApiResult::setContent( $result_array['categorieshtml'], $categoriesHtml );
+ ApiResult::setContentValue( $result_array['categorieshtml'], 'categorieshtml', $categoriesHtml );
}
if ( isset( $prop['links'] ) ) {
$result_array['links'] = $this->formatLinks( $p_result->getLinks() );
if ( isset( $prop['headhtml'] ) ) {
$result_array['headhtml'] = array();
- ApiResult::setContent(
+ ApiResult::setContentValue(
$result_array['headhtml'],
+ 'headhtml',
$context->getOutput()->headElement( $context->getSkin() )
);
}
if ( isset( $prop['indicators'] ) ) {
foreach ( $p_result->getIndicators() as $name => $content ) {
$indicator = array( 'name' => $name );
- ApiResult::setContent( $indicator, $content );
+ ApiResult::setContentValue( $indicator, 'content', $content );
$result_array['indicators'][] = $indicator;
}
}
if ( isset( $prop['wikitext'] ) ) {
$result_array['wikitext'] = array();
- ApiResult::setContent( $result_array['wikitext'], $this->content->serialize( $format ) );
+ ApiResult::setContentValue( $result_array['wikitext'], 'wikitext', $this->content->serialize( $format ) );
if ( !is_null( $this->pstContent ) ) {
$result_array['psttext'] = array();
- ApiResult::setContent( $result_array['psttext'], $this->pstContent->serialize( $format ) );
+ ApiResult::setContentValue( $result_array['psttext'], 'psttext', $this->pstContent->serialize( $format ) );
}
}
if ( isset( $prop['properties'] ) ) {
if ( isset( $prop['limitreporthtml'] ) ) {
$limitreportHtml = EditPage::getPreviewLimitReport( $p_result );
$result_array['limitreporthtml'] = array();
- ApiResult::setContent( $result_array['limitreporthtml'], $limitreportHtml );
+ ApiResult::setContentValue( $result_array['limitreporthtml'], 'limitreporthtml', $limitreportHtml );
}
if ( $params['generatexml'] ) {
$xml = $dom->__toString();
}
$result_array['parsetree'] = array();
- ApiResult::setContent( $result_array['parsetree'], $xml );
+ ApiResult::setContentValue( $result_array['parsetree'], 'parsetree', $xml );
}
$result_mapping = array(
// native language name
$entry['autonym'] = Language::fetchLanguageName( $title->getInterwiki() );
}
- ApiResult::setContent( $entry, $bits[1] );
+ ApiResult::setContentValue( $entry, 'title', $bits[1] );
$result[] = $entry;
}
foreach ( $links as $link => $sortkey ) {
$entry = array();
$entry['sortkey'] = $sortkey;
- ApiResult::setContent( $entry, $link );
+ ApiResult::setContentValue( $entry, 'category', $link );
if ( !isset( $hiddencats[$link] ) ) {
$entry['missing'] = '';
} elseif ( $hiddencats[$link] ) {
foreach ( $nslinks as $title => $id ) {
$entry = array();
$entry['ns'] = $ns;
- ApiResult::setContent( $entry, Title::makeTitle( $ns, $title )->getFullText() );
+ ApiResult::setContentValue( $entry, 'title', Title::makeTitle( $ns, $title )->getFullText() );
if ( $id != 0 ) {
$entry['exists'] = '';
}
$entry['url'] = wfExpandUrl( $title->getFullURL(), PROTO_CURRENT );
}
- ApiResult::setContent( $entry, $title->getFullText() );
+ ApiResult::setContentValue( $entry, 'title', $title->getFullText() );
$result[] = $entry;
}
}
foreach ( $headItems as $tag => $content ) {
$entry = array();
$entry['tag'] = $tag;
- ApiResult::setContent( $entry, $content );
+ ApiResult::setContentValue( $entry, 'content', $content );
$result[] = $entry;
}
foreach ( $properties as $name => $value ) {
$entry = array();
$entry['name'] = $name;
- ApiResult::setContent( $entry, $value );
+ ApiResult::setContentValue( $entry, 'value', $value );
$result[] = $entry;
}
foreach ( $css as $file => $link ) {
$entry = array();
$entry['file'] = $file;
- ApiResult::setContent( $entry, $link );
+ ApiResult::setContentValue( $entry, 'link', $link );
$result[] = $entry;
}
if ( !is_array( $value ) ) {
$value = array( $value );
}
- $apiResult->setIndexedTagName( $value, 'param' );
- $apiResult->setIndexedTagName_recursive( $value, 'param' );
+ ApiResult::setIndexedTagName( $value, 'param' );
+ ApiResult::setIndexedTagNameOnSubarrays( $value, 'param' );
$entry = array_merge( $entry, $value );
$result[] = $entry;
}
private function setIndexedTagNames( &$array, $mapping ) {
foreach ( $mapping as $key => $name ) {
if ( isset( $array[$key] ) ) {
- $this->getResult()->setIndexedTagName( $array[$key], $name );
+ ApiResult::setIndexedTagName( $array[$key], $name );
}
}
}
*/
class ApiProtect extends ApiBase {
public function execute() {
+ global $wgContLang;
+
$params = $this->extractRequestParams();
$pageObj = $this->getTitleOrPageId( $params, 'fromdbmaster' );
}
if ( wfIsInfinity( $expiry[$i] ) ) {
- $expiryarray[$p[0]] = $db->getInfinity();
+ $expiryarray[$p[0]] = 'infinity';
} else {
$exp = strtotime( $expiry[$i] );
if ( $exp < 0 || !$exp ) {
}
$resultProtections[] = array(
$p[0] => $protections[$p[0]],
- 'expiry' => ( $expiryarray[$p[0]] == $db->getInfinity()
- ? 'infinite'
- : wfTimestamp( TS_ISO_8601, $expiryarray[$p[0]] )
- )
+ 'expiry' => $wgContLang->formatExpiry( $expiryarray[$p[0]], TS_ISO_8601, 'infinite' ),
);
}
}
$res['protections'] = $resultProtections;
$result = $this->getResult();
- $result->setIndexedTagName( $res['protections'], 'protection' );
+ ApiResult::setIndexedTagName( $res['protections'], 'protection' );
$result->addValue( null, $this->getModuleName(), $res );
}
*/
public function selectNamedDB( $name, $db, $groups ) {
$this->mDb = $this->getQuery()->getNamedDB( $name, $db, $groups );
+ return $this->mDb;
}
/**
*/
protected function addPageSubItems( $pageId, $data ) {
$result = $this->getResult();
- $result->setIndexedTagName( $data, $this->getModulePrefix() );
+ ApiResult::setIndexedTagName( $data, $this->getModulePrefix() );
return $result->addValue( array( 'query', 'pages', intval( $pageId ) ),
$this->getModuleName(),
if ( !$fit ) {
return false;
}
- $result->setIndexedTagName_internal( array( 'query', 'pages', $pageId,
+ $result->addIndexedTagName( array( 'query', 'pages', $pageId,
$this->getModuleName() ), $elemname );
return true;
* @param string|array $paramValue Parameter value
*/
protected function setContinueEnumParameter( $paramName, $paramValue ) {
- $this->getResult()->setContinueParam( $this, $paramName, $paramValue );
+ $this->getContinuationManager()->addContinueParam( $this, $paramName, $paramValue );
}
/**
*/
protected function setContinueEnumParameter( $paramName, $paramValue ) {
if ( $this->mGeneratorPageSet !== null ) {
- $this->getResult()->setGeneratorContinueParam( $this, $paramName, $paramValue );
+ $this->getContinuationManager()->addGeneratorContinueParam( $this, $paramName, $paramValue );
} else {
parent::setContinueEnumParameter( $paramName, $paramValue );
}
break;
}
}
- $result->setIndexedTagName_internal( array( 'query', $this->getModuleName() ), 'item' );
+ $result->addIndexedTagName( array( 'query', $this->getModuleName() ), 'item' );
}
/**
$vals2['flags'] = isset( $params[$flagsKey] ) ? $params[$flagsKey] : '';
// Indefinite blocks have no expiry time
- if ( SpecialBlock::parseExpiryInput( $params[$durationKey] ) !== wfGetDB( DB_SLAVE )->getInfinity() ) {
+ if ( SpecialBlock::parseExpiryInput( $params[$durationKey] ) !== 'infinity' ) {
$vals2['expiry'] = wfTimestamp( TS_ISO_8601,
strtotime( $params[$durationKey], wfTimestamp( TS_UNIX, $ts ) ) );
}
unset( $params[$idsKey] );
}
if ( isset( $params[$ofieldKey] ) ) {
- $params[] = $params[$ofieldKey];
+ $params[] = 'ofield=' . $params[$ofieldKey];
unset( $params[$ofieldKey] );
}
if ( isset( $params[$nfieldKey] ) ) {
- $params[] = $params[$nfieldKey];
+ $params[] = 'nfield=' . $params[$nfieldKey];
unset( $params[$nfieldKey] );
}
}
$logParam = explode( ':', $key, 3 );
$logParams[$logParam[2]] = $value;
}
- $result->setIndexedTagName( $logParams, 'param' );
- $result->setIndexedTagName_recursive( $logParams, 'param' );
+ ApiResult::setIndexedTagName( $logParams, 'param' );
+ ApiResult::setIndexedTagNameOnSubarrays( $logParams, 'param' );
$vals = array_merge( $vals, $logParams );
}
if ( $this->fld_tags ) {
if ( $row->ts_tags ) {
$tags = explode( ',', $row->ts_tags );
- $this->getResult()->setIndexedTagName( $tags, 'tag' );
+ ApiResult::setIndexedTagName( $tags, 'tag' );
$vals['tags'] = $tags;
} else {
$vals['tags'] = array();
}
if ( $allowException ) {
$data['externalimages'] = (array)$allowFrom;
- $this->getResult()->setIndexedTagName( $data['externalimages'], 'prefix' );
+ ApiResult::setIndexedTagName( $data['externalimages'], 'prefix' );
}
if ( !$config->get( 'DisableLangConversion' ) ) {
$fallbacks[] = array( 'code' => $code );
}
$data['fallback'] = $fallbacks;
- $this->getResult()->setIndexedTagName( $data['fallback'], 'lang' );
+ ApiResult::setIndexedTagName( $data['fallback'], 'lang' );
if ( $wgContLang->hasVariants() ) {
$variants = array();
);
}
$data['variants'] = $variants;
- $this->getResult()->setIndexedTagName( $data['variants'], 'lang' );
+ ApiResult::setIndexedTagName( $data['variants'], 'lang' );
}
if ( $wgContLang->isRTL() ) {
$data['maxuploadsize'] = UploadBase::getMaxUploadSize();
$data['thumblimits'] = $config->get( 'ThumbLimits' );
- $this->getResult()->setIndexedTagName( $data['thumblimits'], 'limit' );
+ ApiResult::setIndexedTagName( $data['thumblimits'], 'limit' );
$data['imagelimits'] = array();
- $this->getResult()->setIndexedTagName( $data['imagelimits'], 'limit' );
+ ApiResult::setIndexedTagName( $data['imagelimits'], 'limit' );
foreach ( $config->get( 'ImageLimits' ) as $k => $limit ) {
$data['imagelimits'][$k] = array( 'width' => $limit[0], 'height' => $limit[1] );
}
'id' => intval( $ns ),
'case' => MWNamespace::isCapitalized( $ns ) ? 'first-letter' : 'case-sensitive',
);
- ApiResult::setContent( $data[$ns], $title );
+ ApiResult::setContentValue( $data[$ns], 'name', $title );
$canonical = MWNamespace::getCanonicalName( $ns );
if ( MWNamespace::hasSubpages( $ns ) ) {
}
}
- $this->getResult()->setIndexedTagName( $data, 'ns' );
+ ApiResult::setIndexedTagName( $data, 'ns' );
return $this->getResult()->addValue( 'query', $property, $data );
}
$item = array(
'id' => intval( $ns )
);
- ApiResult::setContent( $item, strtr( $title, '_', ' ' ) );
+ ApiResult::setContentValue( $item, 'alias', strtr( $title, '_', ' ' ) );
$data[] = $item;
}
sort( $data );
- $this->getResult()->setIndexedTagName( $data, 'ns' );
+ ApiResult::setIndexedTagName( $data, 'ns' );
return $this->getResult()->addValue( 'query', $property, $data );
}
foreach ( SpecialPageFactory::getNames() as $specialpage ) {
if ( isset( $aliases[$specialpage] ) ) {
$arr = array( 'realname' => $specialpage, 'aliases' => $aliases[$specialpage] );
- $this->getResult()->setIndexedTagName( $arr['aliases'], 'alias' );
+ ApiResult::setIndexedTagName( $arr['aliases'], 'alias' );
$data[] = $arr;
}
}
- $this->getResult()->setIndexedTagName( $data, 'specialpage' );
+ ApiResult::setIndexedTagName( $data, 'specialpage' );
return $this->getResult()->addValue( 'query', $property, $data );
}
if ( $caseSensitive ) {
$arr['case-sensitive'] = '';
}
- $this->getResult()->setIndexedTagName( $arr['aliases'], 'alias' );
+ ApiResult::setIndexedTagName( $arr['aliases'], 'alias' );
$data[] = $arr;
}
- $this->getResult()->setIndexedTagName( $data, 'magicword' );
+ ApiResult::setIndexedTagName( $data, 'magicword' );
return $this->getResult()->addValue( 'query', $property, $data );
}
$data[] = $val;
}
- $this->getResult()->setIndexedTagName( $data, 'iw' );
+ ApiResult::setIndexedTagName( $data, 'iw' );
return $this->getResult()->addValue( 'query', $property, $data );
}
}
$result = $this->getResult();
- $result->setIndexedTagName( $data, 'db' );
+ ApiResult::setIndexedTagName( $data, 'db' );
return $this->getResult()->addValue( 'query', $property, $data );
}
$groups = array_intersect( $rights[$group], $allGroups );
if ( $groups ) {
$arr[$type] = $groups;
- $result->setIndexedTagName( $arr[$type], 'group' );
+ ApiResult::setIndexedTagName( $arr[$type], 'group' );
}
}
}
- $result->setIndexedTagName( $arr['rights'], 'permission' );
+ ApiResult::setIndexedTagName( $arr['rights'], 'permission' );
$data[] = $arr;
}
- $result->setIndexedTagName( $data, 'group' );
+ ApiResult::setIndexedTagName( $data, 'group' );
return $result->addValue( 'query', $property, $data );
}
foreach ( array_unique( $this->getConfig()->get( 'FileExtensions' ) ) as $ext ) {
$data[] = array( 'ext' => $ext );
}
- $this->getResult()->setIndexedTagName( $data, 'fe' );
+ ApiResult::setIndexedTagName( $data, 'fe' );
return $this->getResult()->addValue( 'query', $property, $data );
}
'version' => $info['version'],
);
}
- $this->getResult()->setIndexedTagName( $data, 'library' );
+ ApiResult::setIndexedTagName( $data, 'library' );
return $this->getResult()->addValue( 'query', $property, $data );
if ( is_array( $ext['descriptionmsg'] ) ) {
$ret['descriptionmsg'] = $ext['descriptionmsg'][0];
$ret['descriptionmsgparams'] = array_slice( $ext['descriptionmsg'], 1 );
- $this->getResult()->setIndexedTagName( $ret['descriptionmsgparams'], 'param' );
+ ApiResult::setIndexedTagName( $ret['descriptionmsgparams'], 'param' );
} else {
$ret['descriptionmsg'] = $ext['descriptionmsg'];
}
}
}
- $this->getResult()->setIndexedTagName( $data, 'ext' );
+ ApiResult::setIndexedTagName( $data, 'ext' );
return $this->getResult()->addValue( 'query', $property, $data );
}
protected function appendRightsInfo( $property ) {
$config = $this->getConfig();
- $title = Title::newFromText( $config->get( 'RightsPage' ) );
- $url = $title ? wfExpandUrl( $title->getFullURL(), PROTO_CURRENT ) : $config->get( 'RightsUrl' );
+ $rightsPage = $config->get( 'RightsPage' );
+ if ( is_string( $rightsPage ) ) {
+ $title = Title::newFromText( $rightsPage );
+ $url = wfExpandUrl( $title, PROTO_CURRENT );
+ } else {
+ $title = false;
+ $url = $config->get( 'RightsUrl' );
+ }
$text = $config->get( 'RightsText' );
if ( !$text && $title ) {
$text = $title->getPrefixedText();
'semiprotectedlevels' => $config->get( 'SemiprotectedRestrictionLevels' ),
);
- $this->getResult()->setIndexedTagName( $data['types'], 'type' );
- $this->getResult()->setIndexedTagName( $data['levels'], 'level' );
- $this->getResult()->setIndexedTagName( $data['cascadinglevels'], 'level' );
- $this->getResult()->setIndexedTagName( $data['semiprotectedlevels'], 'level' );
+ ApiResult::setIndexedTagName( $data['types'], 'type' );
+ ApiResult::setIndexedTagName( $data['levels'], 'level' );
+ ApiResult::setIndexedTagName( $data['cascadinglevels'], 'level' );
+ ApiResult::setIndexedTagName( $data['semiprotectedlevels'], 'level' );
return $this->getResult()->addValue( 'query', $property, $data );
}
foreach ( $langNames as $code => $name ) {
$lang = array( 'code' => $code );
- ApiResult::setContent( $lang, $name );
+ ApiResult::setContentValue( $lang, 'name', $name );
$data[] = $lang;
}
- $this->getResult()->setIndexedTagName( $data, 'lang' );
+ ApiResult::setIndexedTagName( $data, 'lang' );
return $this->getResult()->addValue( 'query', $property, $data );
}
$displayName = $msg->text();
}
$skin = array( 'code' => $name );
- ApiResult::setContent( $skin, $displayName );
+ ApiResult::setContentValue( $skin, 'name', $displayName );
if ( !isset( $allowed[$name] ) ) {
$skin['unusable'] = '';
}
}
$data[] = $skin;
}
- $this->getResult()->setIndexedTagName( $data, 'skin' );
+ ApiResult::setIndexedTagName( $data, 'skin' );
return $this->getResult()->addValue( 'query', $property, $data );
}
global $wgParser;
$wgParser->firstCallInit();
$tags = array_map( array( $this, 'formatParserTags' ), $wgParser->getTags() );
- $this->getResult()->setIndexedTagName( $tags, 't' );
+ ApiResult::setIndexedTagName( $tags, 't' );
return $this->getResult()->addValue( 'query', $property, $tags );
}
global $wgParser;
$wgParser->firstCallInit();
$hooks = $wgParser->getFunctionHooks();
- $this->getResult()->setIndexedTagName( $hooks, 'h' );
+ ApiResult::setIndexedTagName( $hooks, 'h' );
return $this->getResult()->addValue( 'query', $property, $hooks );
}
public function appendVariables( $property ) {
$variables = MagicWord::getVariableIDs();
- $this->getResult()->setIndexedTagName( $variables, 'v' );
+ ApiResult::setIndexedTagName( $variables, 'v' );
return $this->getResult()->addValue( 'query', $property, $variables );
}
public function appendProtocols( $property ) {
// Make a copy of the global so we don't try to set the _element key of it - bug 45130
$protocols = array_values( $this->getConfig()->get( 'UrlProtocols' ) );
- $this->getResult()->setIndexedTagName( $protocols, 'p' );
+ ApiResult::setIndexedTagName( $protocols, 'p' );
return $this->getResult()->addValue( 'query', $property, $protocols );
}
'subscribers' => array_map( array( 'SpecialVersion', 'arrayToString' ), $subscribers ),
);
- $this->getResult()->setIndexedTagName( $arr['subscribers'], 's' );
+ ApiResult::setIndexedTagName( $arr['subscribers'], 's' );
$data[] = $arr;
}
- $this->getResult()->setIndexedTagName( $data, 'hook' );
+ ApiResult::setIndexedTagName( $data, 'hook' );
return $this->getResult()->addValue( 'query', $property, $data );
}
}
protected function getCurrentUserInfo() {
+ global $wgContLang;
+
$user = $this->getUser();
$result = $this->getResult();
$vals = array();
$vals['blockedbyid'] = $block->getBy();
$vals['blockreason'] = $user->blockedFor();
$vals['blockedtimestamp'] = wfTimestamp( TS_ISO_8601, $block->mTimestamp );
- $vals['blockexpiry'] = $block->getExpiry() === 'infinity'
- ? 'infinite'
- : wfTimestamp( TS_ISO_8601, $block->getExpiry() );
+ $vals['blockexpiry'] = $wgContLang->formatExpiry(
+ $block->getExpiry(), TS_ISO_8601, 'infinite'
+ );
}
}
if ( isset( $this->prop['groups'] ) ) {
$vals['groups'] = $user->getEffectiveGroups();
- $result->setIndexedTagName( $vals['groups'], 'g' ); // even if empty
+ ApiResult::setIndexedTagName( $vals['groups'], 'g' ); // even if empty
}
if ( isset( $this->prop['implicitgroups'] ) ) {
$vals['implicitgroups'] = $user->getAutomaticGroups();
- $result->setIndexedTagName( $vals['implicitgroups'], 'g' ); // even if empty
+ ApiResult::setIndexedTagName( $vals['implicitgroups'], 'g' ); // even if empty
}
if ( isset( $this->prop['rights'] ) ) {
// User::getRights() may return duplicate values, strip them
$vals['rights'] = array_values( array_unique( $user->getRights() ) );
- $result->setIndexedTagName( $vals['rights'], 'r' ); // even if empty
+ ApiResult::setIndexedTagName( $vals['rights'], 'r' ); // even if empty
}
if ( isset( $this->prop['changeablegroups'] ) ) {
$vals['changeablegroups'] = $user->changeableGroups();
- $result->setIndexedTagName( $vals['changeablegroups']['add'], 'g' );
- $result->setIndexedTagName( $vals['changeablegroups']['remove'], 'g' );
- $result->setIndexedTagName( $vals['changeablegroups']['add-self'], 'g' );
- $result->setIndexedTagName( $vals['changeablegroups']['remove-self'], 'g' );
+ ApiResult::setIndexedTagName( $vals['changeablegroups']['add'], 'g' );
+ ApiResult::setIndexedTagName( $vals['changeablegroups']['remove'], 'g' );
+ ApiResult::setIndexedTagName( $vals['changeablegroups']['add-self'], 'g' );
+ ApiResult::setIndexedTagName( $vals['changeablegroups']['remove-self'], 'g' );
}
if ( isset( $this->prop['options'] ) ) {
$acceptLang = array();
foreach ( $langs as $lang => $val ) {
$r = array( 'q' => $val );
- ApiResult::setContent( $r, $lang );
+ ApiResult::setContentValue( $r, 'code', $lang );
$acceptLang[] = $r;
}
- $result->setIndexedTagName( $acceptLang, 'lang' );
+ ApiResult::setIndexedTagName( $acceptLang, 'lang' );
$vals['acceptlang'] = $acceptLang;
}
"apihelp-edit-param-sectiontitle": "The title for a new section.",
"apihelp-edit-param-text": "Page content.",
"apihelp-edit-param-summary": "Edit summary. Also section title when $1section=new and $1sectiontitle is not set.",
+ "apihelp-edit-param-tags": "Change tags to apply to the revision.",
"apihelp-edit-param-minor": "Minor edit.",
"apihelp-edit-param-notminor": "Non-minor edit.",
"apihelp-edit-param-bot": "Mark this edit as bot.",
"apihelp-setnotificationtimestamp-example-pagetimestamp": "Set the notification timestamp for <kbd>Main page</kbd> so all edits since 1 January 2012 are unviewed.",
"apihelp-setnotificationtimestamp-example-allpages": "Reset the notification status for pages in the <kbd>{{ns:user}}</kbd> namespace.",
+ "apihelp-tag-description": "Add or remove change tags from individual revisions or log entries.",
+ "apihelp-tag-param-rcid": "One or more recent changes IDs from which to add or remove the tag.",
+ "apihelp-tag-param-revid": "One or more revision IDs from which to add or remove the tag.",
+ "apihelp-tag-param-logid": "One or more log entry IDs from which to add or remove the tag.",
+ "apihelp-tag-param-add": "Tags to add. Only manually defined tags can be added.",
+ "apihelp-tag-param-remove": "Tags to remove. Only tags that are either manually defined or completely undefined can be removed.",
+ "apihelp-tag-param-reason": "Reason for the change.",
+ "apihelp-tag-example-rev": "Add the <kbd>vandalism</kbd> tag from revision ID 123 without specifying a reason",
+ "apihelp-tag-example-log": "Remove the <kbd>spam</kbd> tag from log entry ID 123 with the reason <kbd>Wrongly applied</kbd>",
+
"apihelp-tokens-description": "Get tokens for data-modifying actions.\n\nThis module is deprecated in favor of [[Special:ApiHelp/query+tokens|action=query&meta=tokens]].",
"apihelp-tokens-param-type": "Types of token to request.",
"apihelp-tokens-example-edit": "Retrieve an edit token (the default).",
"apihelp-dumpfm-description": "Output data in PHP's <code>var_dump()</code> format (pretty-print in HTML).",
"apihelp-json-description": "Output data in JSON format.",
"apihelp-json-param-callback": "If specified, wraps the output into a given function call. For safety, all user-specific data will be restricted.",
- "apihelp-json-param-utf8": "If specified, encodes most (but not all) non-ASCII characters as UTF-8 instead of replacing them with hexadecimal escape sequences.",
+ "apihelp-json-param-utf8": "If specified, encodes most (but not all) non-ASCII characters as UTF-8 instead of replacing them with hexadecimal escape sequences. Default when <var>formatversion</var> is not <kbd>1</kbd>.",
+ "apihelp-json-param-ascii": "If specified, encodes all non-ASCII using hexadecimal escape sequences. Default when <var>formatversion</var> is <kbd>1</kbd>.",
+ "apihelp-json-param-formatversion": "Output formatting:\n;1:Backwards-compatible format (XML-style booleans, <samp>*</samp> keys for content nodes, etc.).\n;2:Experimental modern format. Details may change!\n;latest:Use the latest format (currently <kbd>2</kbd>), may change without warning.",
"apihelp-jsonfm-description": "Output data in JSON format (pretty-print in HTML).",
"apihelp-none-description": "Output nothing.",
"apihelp-php-description": "Output data in serialized PHP format.",
+ "apihelp-php-param-formatversion": "Output formatting:\n;1:Backwards-compatible format (XML-style booleans, <samp>*</samp> keys for content nodes, etc.).\n;2:Experimental modern format. Details may change!\n;latest:Use the latest format (currently <kbd>2</kbd>), may change without warning.",
"apihelp-phpfm-description": "Output data in serialized PHP format (pretty-print in HTML).",
"apihelp-rawfm-description": "Output data with the debugging elements in JSON format (pretty-print in HTML).",
"apihelp-txt-description": "Output data in PHP's <code>print_r()</code> format.",
"api-help-flag-writerights": "This module requires write rights.",
"api-help-flag-mustbeposted": "This module only accepts POST requests.",
"api-help-flag-generator": "This module can be used as a generator.",
+ "api-help-source": "Source: $1",
+ "api-help-source-unknown": "Source: <span class=\"apihelp-unknown\">unknown</span>",
+ "api-help-license": "License: [[$1|$2]]",
+ "api-help-license-noname": "License: [[$1|See link]]",
+ "api-help-license-unknown": "License: <span class=\"apihelp-unknown\">unknown</span>",
"api-help-help-urls": "",
"api-help-parameters": "{{PLURAL:$1|Parameter|Parameters}}:",
"api-help-param-deprecated": "Deprecated.",
"apihelp-edit-param-sectiontitle": "{{doc-apihelp-param|edit|sectiontitle}}",
"apihelp-edit-param-text": "{{doc-apihelp-param|edit|text}}",
"apihelp-edit-param-summary": "{{doc-apihelp-param|edit|summary}}",
+ "apihelp-edit-param-tags": "{{doc-apihelp-param|edit|tags}}",
"apihelp-edit-param-minor": "{{doc-apihelp-param|edit|minor}}\n{{Identical|Minor edit}}",
"apihelp-edit-param-notminor": "{{doc-apihelp-param|edit|notminor}}",
"apihelp-edit-param-bot": "{{doc-apihelp-param|edit|bot}}",
"apihelp-setnotificationtimestamp-example-page": "{{doc-apihelp-example|setnotificationtimestamp}}",
"apihelp-setnotificationtimestamp-example-pagetimestamp": "{{doc-apihelp-example|setnotificationtimestamp}}",
"apihelp-setnotificationtimestamp-example-allpages": "{{doc-apihelp-example|setnotificationtimestamp}}",
+ "apihelp-tag-description": "{{doc-apihelp-description|tag}}",
+ "apihelp-tag-param-rcid": "{{doc-apihelp-param|tag|rcid}}",
+ "apihelp-tag-param-revid": "{{doc-apihelp-param|tag|revid}}",
+ "apihelp-tag-param-logid": "{{doc-apihelp-param|tag|logid}}",
+ "apihelp-tag-param-add": "{{doc-apihelp-param|tag|add}}",
+ "apihelp-tag-param-remove": "{{doc-apihelp-param|tag|remove}}",
+ "apihelp-tag-param-reason": "{{doc-apihelp-param|tag|reason}}",
+ "apihelp-tag-example-rev": "{{doc-apihelp-example|tag}}",
+ "apihelp-tag-example-log": "{{doc-apihelp-example|tag}}",
"apihelp-tokens-description": "{{doc-apihelp-description|tokens}}",
"apihelp-tokens-param-type": "{{doc-apihelp-param|tokens|type}}",
"apihelp-tokens-example-edit": "{{doc-apihelp-example|tokens}}",
"apihelp-json-description": "{{doc-apihelp-description|json|seealso=* {{msg-mw|apihelp-jsonfm-description}}}}",
"apihelp-json-param-callback": "{{doc-apihelp-param|json|callback}}",
"apihelp-json-param-utf8": "{{doc-apihelp-param|json|utf8}}",
+ "apihelp-json-param-ascii": "{{doc-apihelp-param|json|ascii}}",
+ "apihelp-json-param-formatversion": "{{doc-apihelp-param|json|formatversion}}",
"apihelp-jsonfm-description": "{{doc-apihelp-description|jsonfm|seealso=* {{msg-mw|apihelp-json-description}}}}",
"apihelp-none-description": "{{doc-apihelp-description|none}}",
"apihelp-php-description": "{{doc-apihelp-description|php|seealso=* {{msg-mw|apihelp-phpfm-description}}}}",
+ "apihelp-php-param-formatversion": "{{doc-apihelp-param|json|formatversion}}",
"apihelp-phpfm-description": "{{doc-apihelp-description|phpfm|seealso=* {{msg-mw|apihelp-php-description}}}}",
"apihelp-rawfm-description": "{{doc-apihelp-description|rawfm|seealso=* {{msg-mw|apihelp-raw-description}}}}",
"apihelp-txt-description": "{{doc-apihelp-description|txt|seealso=* {{msg-mw|apihelp-txtfm-description}}}}",
"api-help-flag-writerights": "Flag displayed for an API module that requires write rights",
"api-help-flag-mustbeposted": "Flag displayed for an API module that only accepts POST requests",
"api-help-flag-generator": "Flag displayed for an API module that can be used as a generator",
+ "api-help-source": "Displayed in the flags box to indicate the source of an API module.\n\nParameters:\n* $1 - Possibly-localised extension name, or \"MediaWiki\" if it's a core module\n* $2 - Non-localised extension name.\n\nSee also:\n* {{msg-mw|api-help-source-unknown}}",
+ "api-help-source-unknown": "Displayed in the flags box to indicate that the source of an API module is not known.\n\nSee also:\n* {{msg-mw|api-help-source}}",
+ "api-help-license": "Displayed in the flags box to indicate the license of an API module.\n\nParameters:\n* $1 - Page to link to display the full license text\n* $2 - Display text for the link\n\nSee also:\n* {{msg-mw|api-help-license-noname}}\n* {{msg-mw|api-help-license-unknown}}",
+ "api-help-license-noname": "Displayed in the flags box to indicate the license of an API module, when the tag for the license is not known.\n\nParameters:\n* $1 - Page to link to display the full license text\n\nSee also:\n* {{msg-mw|api-help-license}}\n* {{msg-mw|api-help-license-unknown}}",
+ "api-help-license-unknown": "Displayed in the flags box to indicate that the license of the API module is not known.\n\nSee also:\n* {{msg-mw|api-help-license}}\n* {{msg-mw|api-help-license-noname}}",
"api-help-help-urls": "{{optional}} Label for the API help urls section\n\nParameters:\n* $1 - Number of urls to be displayed",
"api-help-parameters": "Label for the API help parameters section\n\nParameters:\n* $1 - Number of parameters to be displayed\n{{Identical|Parameter}}",
"api-help-param-deprecated": "Displayed in the API help for any deprecated parameter\n{{Identical|Deprecated}}",