return new self( $sv );
}
+ /**
+ * Splits this Status object into two new Status objects, one which contains only
+ * the error messages, and one that contains the warnings, only. The returned array is
+ * defined as:
+ * array(
+ * 0 => object(Status) # the Status with error messages, only
+ * 1 => object(Status) # The Status with warning messages, only
+ * )
+ *
+ * @return array
+ */
+ public function splitByErrorType() {
+ list( $errorsOnlyStatusValue, $warningsOnlyStatusValue ) = $this->sv->splitByErrorType();
+ $errorsOnlyStatus = new Status( $errorsOnlyStatusValue );
+ $warningsOnlyStatus = new Status( $warningsOnlyStatusValue );
+ $errorsOnlyStatus->cleanCallback = $warningsOnlyStatus->cleanCallback = $this->cleanCallback;
+
+ return [ $errorsOnlyStatus, $warningsOnlyStatus ];
+ }
+
/**
* Change operation result
*
/**
* Return the message for a single error.
+ *
* @param mixed $error With an array & two values keyed by
* 'message' and 'params', use those keys-value pairs.
* Otherwise, if its an array, just use the first value as the
/** @var Message|null I18n message to display in case of UI or FAIL */
public $message = null;
+ /** @var string Whether the $message is an error or warning message, for styling reasons */
+ public $messageType = 'warning';
+
/**
* @var string|null Local user name from authentication.
* May be null if the authentication passed but no local user is known.
$ret = new AuthenticationResponse;
$ret->status = AuthenticationResponse::FAIL;
$ret->message = $msg;
+ $ret->messageType = 'error';
return $ret;
}
/**
* @param AuthenticationRequest[] $reqs AuthenticationRequests needed to continue
* @param Message $msg
+ * @param string $msgtype
* @return AuthenticationResponse
* @see AuthenticationResponse::UI
*/
- public static function newUI( array $reqs, Message $msg ) {
+ public static function newUI( array $reqs, Message $msg, $msgtype = 'warning' ) {
if ( !$reqs ) {
throw new \InvalidArgumentException( '$reqs may not be empty' );
}
+ if ( $msgtype !== 'warning' && $msgtype !== 'error' ) {
+ throw new \InvalidArgumentException( $msgtype . ' is not a valid message type.' );
+ }
$ret = new AuthenticationResponse;
$ret->status = AuthenticationResponse::UI;
$ret->neededRequests = $reqs;
$ret->message = $msg;
+ $ret->messageType = $msgtype;
return $ret;
}
$req = new ConfirmLinkAuthenticationRequest( $maybeLink );
return AuthenticationResponse::newUI(
[ $req ],
- wfMessage( 'authprovider-confirmlink-message' )
+ wfMessage( 'authprovider-confirmlink-message' ),
+ 'warning'
);
}
'linkOk', wfMessage( 'ok' ), wfMessage( 'authprovider-confirmlink-ok-help' )
)
],
- $combinedStatus->getMessage( 'authprovider-confirmlink-failed' )
+ $combinedStatus->getMessage( 'authprovider-confirmlink-failed' ),
+ 'error'
);
}
}
$req = AuthenticationRequest::getRequestByClass( $reqs, get_class( $needReq ) );
if ( !$req || !array_key_exists( 'retype', $req->getFieldInfo() ) ) {
- return AuthenticationResponse::newUI( $needReqs, $data->msg );
+ return AuthenticationResponse::newUI( $needReqs, $data->msg, 'warning' );
}
if ( $req->password !== $req->retype ) {
- return AuthenticationResponse::newUI( $needReqs, new \Message( 'badretype' ) );
+ return AuthenticationResponse::newUI( $needReqs, new \Message( 'badretype' ), 'error' );
}
$req->username = $user->getName();
$status = $this->manager->allowsAuthenticationDataChange( $req );
if ( !$status->isGood() ) {
- return AuthenticationResponse::newUI( $needReqs, $status->getMessage() );
+ return AuthenticationResponse::newUI( $needReqs, $status->getMessage(), 'error' );
}
$this->manager->changeAuthenticationData( $req );
$this->getOutput()->addModuleStyles( 'mediawiki.htmlform.styles' );
$html = ''
- . $this->getErrors( $submitResult )
+ . $this->getErrorsOrWarnings( $submitResult, 'error' )
+ . $this->getErrorsOrWarnings( $submitResult, 'warning' )
. $this->getHeaderText()
. $this->getBody()
. $this->getHiddenFields()
*
* @param string|array|Status $errors
*
+ * @deprecated since 1.28, use getErrorsOrWarnings() instead
+ *
* @return string
*/
public function getErrors( $errors ) {
- if ( $errors instanceof Status ) {
- if ( $errors->isOK() ) {
- $errorstr = '';
+ wfDeprecated( __METHOD__ );
+ return $this->getErrorsOrWarnings( $errors, 'error' );
+ }
+
+ /**
+ * Returns a formatted list of errors or warnings from the given elements.
+ *
+ * @param string|array|Status $elements The set of errors/warnings to process.
+ * @param string $elementsType Should warnings or errors be returned. This is meant
+ * for Status objects, all other valid types are always considered as errors.
+ * @return string
+ */
+ public function getErrorsOrWarnings( $elements, $elementsType ) {
+ if ( !in_array( $elementsType, [ 'error', 'warning' ], true ) ) {
+ throw new DomainException( $elementsType . ' is not a valid type.' );
+ }
+ $elementstr = false;
+ if ( $elements instanceof Status ) {
+ list( $errorStatus, $warningStatus ) = $elements->splitByErrorType();
+ $status = $elementsType === 'error' ? $errorStatus : $warningStatus;
+ if ( $status->isGood() ) {
+ $elementstr = '';
} else {
- $errorstr = $this->getOutput()->parse( $errors->getWikiText() );
+ $elementstr = $this->getOutput()->parse(
+ $status->getWikiText()
+ );
}
- } elseif ( is_array( $errors ) ) {
- $errorstr = $this->formatErrors( $errors );
- } else {
- $errorstr = $errors;
+ } elseif ( is_array( $elements ) && $elementsType === 'error' ) {
+ $elementstr = $this->formatErrors( $elements );
+ } elseif ( $elementsType === 'error' ) {
+ $elementstr = $elements;
}
- return $errorstr
- ? Html::rawElement( 'div', [ 'class' => 'error' ], $errorstr )
+ return $elementstr
+ ? Html::rawElement( 'div', [ 'class' => $elementsType ], $elementstr )
: '';
}
*/
class OOUIHTMLForm extends HTMLForm {
private $oouiErrors;
+ private $oouiWarnings;
public function __construct( $descriptor, $context = null, $messagePrefix = '' ) {
parent::__construct( $descriptor, $context, $messagePrefix );
}
/**
- * @param string|array|Status $err
+ * @param string|array|Status $elements
+ * @param string $elementsType
* @return string
*/
- function getErrors( $err ) {
- if ( !$err ) {
+ function getErrorsOrWarnings( $elements, $elementsType ) {
+ if ( !in_array( $elementsType, [ 'error', 'warning' ] ) ) {
+ throw new DomainException( $elementsType . ' is not a valid type.' );
+ }
+ if ( !$elements ) {
$errors = [];
- } elseif ( $err instanceof Status ) {
- if ( $err->isOK() ) {
+ } elseif ( $elements instanceof Status ) {
+ if ( $elements->isGood() ) {
$errors = [];
} else {
- $errors = $err->getErrorsByType( 'error' );
+ $errors = $elements->getErrorsByType( $elementsType );
foreach ( $errors as &$error ) {
// Input: array( 'message' => 'foo', 'errors' => array( 'a', 'b', 'c' ) )
// Output: array( 'foo', 'a', 'b', 'c' )
$error = array_merge( [ $error['message'] ], $error['params'] );
}
}
- } else {
- $errors = $err;
+ } elseif ( $elementsType === 'errors' ) {
+ $errors = $elements;
if ( !is_array( $errors ) ) {
$errors = [ $errors ];
}
+ } else {
+ $errors = [];
}
foreach ( $errors as &$error ) {
}
// Used in getBody()
- $this->oouiErrors = $errors;
+ if ( $elementsType === 'error' ) {
+ $this->oouiErrors = $errors;
+ } else {
+ $this->oouiWarnings = $errors;
+ }
return '';
}
if ( $this->oouiErrors ) {
$classes[] = 'mw-htmlform-ooui-header-errors';
}
- if ( $this->mHeader || $this->oouiErrors ) {
+ if ( $this->oouiWarnings ) {
+ $classes[] = 'mw-htmlform-ooui-header-warnings';
+ }
+ if ( $this->mHeader || $this->oouiErrors || $this->oouiWarnings ) {
// if there's no header, don't create an (empty) LabelWidget, simply use a placeholder
if ( $this->mHeader ) {
$element = new OOUI\LabelWidget( [ 'label' => new OOUI\HtmlSnippet( $this->mHeader ) ] );
[
'align' => 'top',
'errors' => $this->oouiErrors,
+ 'notices' => $this->oouiWarnings,
'classes' => $classes,
]
)
return $result;
}
+ /**
+ * Splits this StatusValue object into two new StatusValue objects, one which contains only
+ * the error messages, and one that contains the warnings, only. The returned array is
+ * defined as:
+ * array(
+ * 0 => object(StatusValue) # the StatusValue with error messages, only
+ * 1 => object(StatusValue) # The StatusValue with warning messages, only
+ * )
+ *
+ * @return array
+ */
+ public function splitByErrorType() {
+ $errorsOnlyStatusValue = clone $this;
+ $warningsOnlyStatusValue = clone $this;
+ $warningsOnlyStatusValue->ok = true;
+
+ $errorsOnlyStatusValue->errors = $warningsOnlyStatusValue->errors = [];
+ foreach ( $this->errors as $item ) {
+ if ( $item['type'] === 'warning' ) {
+ $warningsOnlyStatusValue->errors[] = $item;
+ } else {
+ $errorsOnlyStatusValue->errors[] = $item;
+ }
+ };
+
+ return [ $errorsOnlyStatusValue, $warningsOnlyStatusValue ];
+ }
+
/**
* Returns whether the operation completed and didn't have any error or
* warnings
$this->authAction = $this->isSignup() ? AuthManager::ACTION_CREATE_CONTINUE
: AuthManager::ACTION_LOGIN_CONTINUE;
$this->authRequests = $response->neededRequests;
- $this->mainLoginForm( $response->neededRequests, $response->message, 'warning' );
+ $this->mainLoginForm( $response->neededRequests, $response->message, $response->messageType );
break;
default:
throw new LogicException( 'invalid AuthenticationResponse' );
$form = $this->getAuthForm( $requests, $this->authAction, $msg, $msgtype );
$form->prepareForm();
- $formHtml = $form->getHTML( $msg ? Status::newFatal( $msg ) : false );
+ $submitStatus = Status::newGood();
+ if ( $msg && $msgtype === 'warning' ) {
+ $submitStatus->warning( $msg );
+ } elseif ( $msg && $msgtype === 'error' ) {
+ $submitStatus->fatal( $msg );
+ }
+ $formHtml = $form->getHTML( $submitStatus );
$out->addHTML( $this->getPageHtml( $formHtml ) );
}
@colorButtonTextActive: @colorGray7;
@colorDisabledText: @colorGray12;
@colorErrorText: #c00;
+@colorWarningText: #705000;
// UI colors
@colorFieldBorder: @colorGray12;
//
// Styleguide 5.2.
.error,
+ .warning,
.errorbox,
.warningbox,
.successbox {
color: @colorErrorText;
border: 1px solid #fac5c5;
background-color: #fae3e3;
- text-shadow: 0 1px #fae3e3;
+ }
+
+ // Colours taken from those for .warningbox in shared.css
+ .warning {
+ color: @colorWarningText;
+ border: 1px solid #fde29b;
+ background-color: #fdf1d1;
}
// This specifies styling for individual field validation error messages.
];
}
+ /**
+ * @dataProvider provideErrorsWarningsOnly
+ * @covers Status::getErrorsOnlyStatus
+ * @covers Status::getWarningsOnlyStatus
+ */
+ public function testGetErrorsWarningsOnlyStatus( $errorText, $warningText, $type, $errorResult,
+ $warningResult
+ ) {
+ $status = Status::newGood();
+ if ( $errorText ) {
+ $status->fatal( $errorText );
+ }
+ if ( $warningText ) {
+ $status->warning( $warningText );
+ }
+ $testStatus = $status->splitByErrorType()[$type];
+ $this->assertEquals( $errorResult, $testStatus->getErrorsByType( 'error' ) );
+ $this->assertEquals( $warningResult, $testStatus->getErrorsByType( 'warning' ) );
+ }
+
+ public static function provideErrorsWarningsOnly() {
+ return [
+ [
+ 'Just an error',
+ 'Just a warning',
+ 0,
+ [
+ 0 => [
+ 'type' => 'error',
+ 'message' => 'Just an error',
+ 'params' => []
+ ],
+ ],
+ [],
+ ], [
+ 'Just an error',
+ 'Just a warning',
+ 1,
+ [],
+ [
+ 0 => [
+ 'type' => 'warning',
+ 'message' => 'Just a warning',
+ 'params' => []
+ ],
+ ],
+ ], [
+ null,
+ null,
+ 1,
+ [],
+ [],
+ ], [
+ null,
+ null,
+ 0,
+ [],
+ [],
+ ]
+ ];
+ }
+
}
public function testConstructors( $constructor, $args, $expect ) {
if ( is_array( $expect ) ) {
$res = new AuthenticationResponse();
+ $res->messageType = 'warning';
foreach ( $expect as $field => $value ) {
$res->$field = $value;
}
[ 'newFail', [ $msg ], [
'status' => AuthenticationResponse::FAIL,
'message' => $msg,
+ 'messageType' => 'error',
] ],
[ 'newRestart', [ $msg ], [
'status' => AuthenticationResponse::UI,
'neededRequests' => [ $req ],
'message' => $msg,
+ 'messageType' => 'warning',
+ ] ],
+
+ [ 'newUI', [ [ $req ], $msg, 'warning' ], [
+ 'status' => AuthenticationResponse::UI,
+ 'neededRequests' => [ $req ],
+ 'message' => $msg,
+ 'messageType' => 'warning',
+ ] ],
+
+ [ 'newUI', [ [ $req ], $msg, 'error' ], [
+ 'status' => AuthenticationResponse::UI,
+ 'neededRequests' => [ $req ],
+ 'message' => $msg,
+ 'messageType' => 'error',
] ],
[ 'newUI', [ [], $msg ],
new \InvalidArgumentException( '$reqs may not be empty' )