*/
const PARAM_EXTRA_NAMESPACES = 18;
+ /**
+ * (boolean) Is the parameter sensitive? Note 'password'-type fields are
+ * always sensitive regardless of the value of this field.
+ * @since 1.29
+ */
+ const PARAM_SENSITIVE = 19;
+
+ /**
+ * (array) When PARAM_TYPE is an array, this indicates which of the values are deprecated.
+ * Keys are the deprecated parameter values, values define the warning
+ * message to emit: either boolean true (to use a default message) or a
+ * $msg for ApiBase::makeMessage().
+ * @since 1.30
+ */
+ const PARAM_DEPRECATED_VALUES = 20;
+
/**@}*/
const ALL_DEFAULT_STRING = '*';
/**
* Indicates whether this module requires write mode
+ *
+ * This should return true for modules that may require synchronous database writes.
+ * Modules that do not need such writes should also not rely on master database access,
+ * since only read queries are needed and each master DB is a single point of failure.
+ * Additionally, requests that only need replica DBs can be efficiently routed to any
+ * datacenter via the Promise-Non-Write-API-Action header.
+ *
* @return bool
*/
public function isWriteMode() {
/**
* Gets a default replica DB connection object
- * @return Database
+ * @return IDatabase
*/
protected function getDB() {
if ( !isset( $this->mSlaveDB ) ) {
$deprecated = isset( $paramSettings[self::PARAM_DEPRECATED] )
? $paramSettings[self::PARAM_DEPRECATED]
: false;
+ $deprecatedValues = isset( $paramSettings[self::PARAM_DEPRECATED_VALUES] )
+ ? $paramSettings[self::PARAM_DEPRECATED_VALUES]
+ : [];
$required = isset( $paramSettings[self::PARAM_REQUIRED] )
? $paramSettings[self::PARAM_REQUIRED]
: false;
} else {
$type = 'NULL'; // allow everything
}
+
+ if ( $type == 'password' || !empty( $paramSettings[self::PARAM_SENSITIVE] ) ) {
+ $this->getMain()->markParamsSensitive( $encParamName );
+ }
}
if ( $type == 'boolean' ) {
}
$this->addDeprecation( [ 'apiwarn-deprecation-parameter', $encParamName ], $feature );
}
+
+ // Set a warning if a deprecated parameter value has been passed
+ $usedDeprecatedValues = $deprecatedValues && $value !== false
+ ? array_intersect( array_keys( $deprecatedValues ), (array)$value )
+ : [];
+ if ( $usedDeprecatedValues ) {
+ $feature = "$encParamName=";
+ $m = $this;
+ while ( !$m->isMain() ) {
+ $p = $m->getParent();
+ $name = $m->getModuleName();
+ $param = $p->encodeParamName( $p->getModuleManager()->getModuleGroup( $name ) );
+ $feature = "{$param}={$name}&{$feature}";
+ $m = $p;
+ }
+ foreach ( $usedDeprecatedValues as $v ) {
+ $msg = $deprecatedValues[$v];
+ if ( $msg === true ) {
+ $msg = [ 'apiwarn-deprecation-parameter', "$encParamName=$v" ];
+ }
+ $this->addDeprecation( $msg, "$feature$v" );
+ }
+ }
} elseif ( $required ) {
$this->dieWithError( [ 'apierror-missingparam', $paramName ] );
}
throw new MWException( 'Successful status passed to ApiBase::dieStatus' );
}
+ // ApiUsageException needs a fatal status, but this method has
+ // historically accepted any non-good status. Convert it if necessary.
+ $status->setOK( false );
+ if ( !$status->getErrorsByType( 'error' ) ) {
+ $newStatus = Status::newGood();
+ foreach ( $status->getErrorsByType( 'warning' ) as $err ) {
+ call_user_func_array(
+ [ $newStatus, 'fatal' ],
+ array_merge( [ $err['message'] ], $err['params'] )
+ );
+ }
+ if ( !$newStatus->getErrorsByType( 'error' ) ) {
+ $newStatus->fatal( 'unknownerror-nocode' );
+ }
+ $status = $newStatus;
+ }
+
throw new ApiUsageException( $this, $status );
}
*/
/**
- * Return the description message.
+ * Return the summary message.
*
+ * This is a one-line description of the module, suitable for display in a
+ * list of modules.
+ *
+ * @since 1.30
* @return string|array|Message
*/
- protected function getDescriptionMessage() {
- return "apihelp-{$this->getModulePath()}-description";
+ protected function getSummaryMessage() {
+ return "apihelp-{$this->getModulePath()}-summary";
+ }
+
+ /**
+ * Return the extended help text message.
+ *
+ * This is additional text to display at the top of the help section, below
+ * the summary.
+ *
+ * @since 1.30
+ * @return string|array|Message
+ */
+ protected function getExtendedDescription() {
+ return [ [
+ "apihelp-{$this->getModulePath()}-extended-description",
+ 'api-help-no-extended-description',
+ ] ];
+ }
+
+ /**
+ * Get final module summary
+ *
+ * Ideally this will just be the getSummaryMessage(). However, for
+ * backwards compatibility, if that message does not exist then the first
+ * line of wikitext from the description message will be used instead.
+ *
+ * @since 1.30
+ * @return Message
+ */
+ public function getFinalSummary() {
+ $msg = ApiBase::makeMessage( $this->getSummaryMessage(), $this->getContext(), [
+ $this->getModulePrefix(),
+ $this->getModuleName(),
+ $this->getModulePath(),
+ ] );
+ if ( !$msg->exists() ) {
+ wfDeprecated( 'API help "description" messages', '1.30' );
+ $msg = ApiBase::makeMessage( $this->getDescriptionMessage(), $this->getContext(), [
+ $this->getModulePrefix(),
+ $this->getModuleName(),
+ $this->getModulePath(),
+ ] );
+ $msg = ApiBase::makeMessage( 'rawmessage', $this->getContext(), [
+ preg_replace( '/\n.*/s', '', $msg->text() )
+ ] );
+ }
+ return $msg;
}
/**
$desc = (string)$desc;
}
- $msg = ApiBase::makeMessage( $this->getDescriptionMessage(), $this->getContext(), [
+ $summary = ApiBase::makeMessage( $this->getSummaryMessage(), $this->getContext(), [
$this->getModulePrefix(),
$this->getModuleName(),
$this->getModulePath(),
] );
- if ( !$msg->exists() ) {
- $msg = $this->msg( 'api-help-fallback-description', $desc );
+ $extendedDescription = ApiBase::makeMessage(
+ $this->getExtendedDescription(), $this->getContext(), [
+ $this->getModulePrefix(),
+ $this->getModuleName(),
+ $this->getModulePath(),
+ ]
+ );
+
+ if ( $summary->exists() ) {
+ $msgs = [ $summary, $extendedDescription ];
+ } else {
+ wfDeprecated( 'API help "description" messages', '1.30' );
+ $description = ApiBase::makeMessage( $this->getDescriptionMessage(), $this->getContext(), [
+ $this->getModulePrefix(),
+ $this->getModuleName(),
+ $this->getModulePath(),
+ ] );
+ if ( !$description->exists() ) {
+ $description = $this->msg( 'api-help-fallback-description', $desc );
+ }
+ $msgs = [ $description ];
}
- $msgs = [ $msg ];
Hooks::run( 'APIGetDescriptionMessages', [ $this, &$msgs ] );
$params['token'] = [
ApiBase::PARAM_TYPE => 'string',
ApiBase::PARAM_REQUIRED => true,
+ ApiBase::PARAM_SENSITIVE => true,
ApiBase::PARAM_HELP_MSG => [
'api-help-param-token',
$this->needsToken(),
}
$valueMsgs = $settings[ApiBase::PARAM_HELP_MSG_PER_VALUE];
+ $deprecatedValues = isset( $settings[ApiBase::PARAM_DEPRECATED_VALUES] )
+ ? $settings[ApiBase::PARAM_DEPRECATED_VALUES]
+ : [];
+
foreach ( $settings[ApiBase::PARAM_TYPE] as $value ) {
if ( isset( $valueMsgs[$value] ) ) {
$msg = $valueMsgs[$value];
$m = new ApiHelpParamValueMessage(
$value,
[ $m->getKey(), 'api-help-param-no-description' ],
- $m->getParams()
+ $m->getParams(),
+ isset( $deprecatedValues[$value] )
);
$msgs[$param][] = $m->setContext( $this->getContext() );
} else {
$this->dieWithErrorOrDebug( $this->parseMsgInternal( $error ) );
}
+ /**
+ * Return the description message.
+ *
+ * This is additional text to display on the help page after the summary.
+ *
+ * @deprecated since 1.30
+ * @return string|array|Message
+ */
+ protected function getDescriptionMessage() {
+ return [ [
+ "apihelp-{$this->getModulePath()}-description",
+ "apihelp-{$this->getModulePath()}-summary",
+ ] ];
+ }
+
/**@}*/
}