setting in the relevant section of $wgLBFactoryConf.
* User::newSystemUser() may be used to simplify the creation of passwordless
"system" users for logged actions from scripts and extensions.
+* Extensions can now return detailed error information via the API when
+ preventing user actions using 'getUserPermissionsErrors' and similar hooks
+ by using ApiMessage instances instead of strings for the $result value.
==== External libraries ====
'getUserPermissionsErrors': Add a permissions error when permissions errors are
checked for. Use instead of userCan for most cases. Return false if the user
can't do it, and populate $result with the reason in the form of
-array( messagename, param1, param2, ... ). For consistency, error messages
+array( messagename, param1, param2, ... ) or a MessageSpecifier instance (you
+might want to use ApiMessage to provide machine-readable details for the API).
+For consistency, error messages
should be plain text with no special coloring, bolding, etc. to show that
they're errors; presenting them properly to the user as errors is done by the
caller.
called only if expensive checks are enabled. Add a permissions error when
permissions errors are checked for. Return false if the user can't do it, and
populate $result with the reason in the form of array( messagename, param1,
-param2, ... ). For consistency, error messages should be plain text with no
+param2, ... ) or a MessageSpecifier instance (you might want to use ApiMessage
+to provide machine-readable details for the API). For consistency, error
+messages should be plain text with no
special coloring, bolding, etc. to show that they're errors; presenting them
properly to the user as errors is done by the caller.
$title: Title object being checked against
$out = array();
foreach ( $args as $errors ) {
foreach ( $errors as $params ) {
+ $originalParams = $params;
+ if ( $params[0] instanceof MessageSpecifier ) {
+ $msg = $params[0];
+ $params = array_merge( array( $msg->getKey() ), $msg->getParams() );
+ }
# @todo FIXME: Sometimes get nested arrays for $params,
# which leads to E_NOTICEs
$spec = implode( "\t", $params );
- $out[$spec] = $params;
+ $out[$spec] = $originalParams;
}
}
return array_values( $out );
* - secure : does cheap and expensive checks, using the master as needed
* @param array $ignoreErrors Array of Strings Set this to a list of message keys
* whose corresponding errors may be ignored.
- * @return array Array of arguments to wfMessage to explain permissions problems.
+ * @return array Array of arrays of the arguments to wfMessage to explain permissions problems.
*/
public function getUserPermissionsErrors(
$action, $user, $rigor = 'secure', $ignoreErrors = array()
// Remove the errors being ignored.
foreach ( $errors as $index => $error ) {
- $error_key = is_array( $error ) ? $error[0] : $error;
+ $errKey = is_array( $error ) ? $error[0] : $error;
- if ( in_array( $error_key, $ignoreErrors ) ) {
+ if ( in_array( $errKey, $ignoreErrors ) ) {
+ unset( $errors[$index] );
+ }
+ if ( $errKey instanceof MessageSpecifier && in_array( $errKey->getKey(), $ignoreErrors ) ) {
unset( $errors[$index] );
}
}
} elseif ( $result !== '' && is_string( $result ) ) {
// A string representing a message-id
$errors[] = array( $result );
+ } elseif ( $result instanceof MessageSpecifier ) {
+ // A message specifier representing an error
+ $errors[] = array( $result );
} elseif ( $result === false ) {
// a generic "We don't want them to do that"
$errors[] = array( 'badaccess-group0' );
*
* @since 1.23
* @param Status $status
+ * @param array|null &$extraData Set if extra data from IApiMessage is available (since 1.27)
* @return array Array of code and error string
* @throws MWException
*/
- public function getErrorFromStatus( $status ) {
+ public function getErrorFromStatus( $status, &$extraData = null ) {
if ( $status->isGood() ) {
throw new MWException( 'Successful status passed to ApiBase::dieStatus' );
}
// error messages.
if ( $errors[0] instanceof Message ) {
$msg = $errors[0];
- $code = $msg->getKey();
+ if ( $msg instanceof IApiMessage ) {
+ $extraData = $msg->getApiData();
+ $code = $msg->getApiCode();
+ } else {
+ $code = $msg->getKey();
+ }
} else {
$code = array_shift( $errors[0] );
$msg = wfMessage( $code, $errors[0] );
* @throws UsageException always
*/
public function dieStatus( $status ) {
- list( $code, $msg ) = $this->getErrorFromStatus( $status );
- $this->dieUsage( $msg, $code );
+ $extraData = null;
+ list( $code, $msg ) = $this->getErrorFromStatus( $status, $extraData );
+ $this->dieUsage( $msg, $code, 0, $extraData );
}
// @codingStandardsIgnoreStart Allow long lines. Cannot split these.
$error = array( $error );
}
$parsed = $this->parseMsg( $error );
- $this->dieUsage( $parsed['info'], $parsed['code'] );
+ $extraData = isset( $parsed['data'] ) ? $parsed['data'] : null;
+ $this->dieUsage( $parsed['info'], $parsed['code'], 0, $extraData );
}
/**
$key = array_shift( $error );
}
+ if ( $key instanceof IApiMessage ) {
+ return array(
+ 'code' => $key->getApiCode(),
+ 'info' => $key->inLanguage( 'en' )->useDatabase( false )->text(),
+ 'data' => $key->getApiData()
+ );
+ }
+
if ( isset( self::$messageMap[$key] ) ) {
return array(
'code' => wfMsgReplaceArgs( self::$messageMap[$key]['code'], $error ),
$data['invalidparameter'] = $parameter;
$parsed = $this->parseMsg( $error );
+ if ( isset( $parsed['data'] ) ) {
+ $data = array_merge( $data, $parsed['data'] );
+ }
+
$this->dieUsage( $parsed['info'], $parsed['code'], 0, $data );
}