* @ingroup API
*/
class ApiOptions extends ApiBase {
+ /** @var User User account to modify */
+ private $userForUpdates;
+
/**
* Changes preferences of the current user.
*/
public function execute() {
- if ( $this->getUser()->isAnon() ) {
+ $user = $this->getUserForUpdates();
+ if ( !$user || $user->isAnon() ) {
$this->dieWithError(
[ 'apierror-mustbeloggedin', $this->msg( 'action-editmyoptions' ) ], 'notloggedin'
);
$this->dieWithError( [ 'apierror-missingparam', 'optionname' ] );
}
- // Load the user from the master to reduce CAS errors on double post (T95839)
- $user = $this->getUser()->getInstanceForUpdate();
- if ( !$user ) {
- $this->dieWithError(
- [ 'apierror-mustbeloggedin', $this->msg( 'action-editmyoptions' ) ], 'notloggedin'
- );
- }
-
- if ( $params['reset'] ) {
- $user->resetOptions( $params['resetkinds'], $this->getContext() );
- $changed = true;
+ $resetKinds = $params['resetkinds'];
+ if ( !$params['reset'] ) {
+ $resetKinds = [];
}
$changes = [];
$newValue = $params['optionvalue'] ?? null;
$changes[$params['optionname']] = $newValue;
}
+
+ Hooks::run( 'ApiOptions', [ $this, $user, $changes, $resetKinds ] );
+
+ if ( $resetKinds ) {
+ $this->resetPreferences( $resetKinds );
+ $changed = true;
+ }
+
if ( !$changed && !count( $changes ) ) {
$this->dieWithError( 'apierror-nochanges' );
}
- $preferencesFactory = MediaWikiServices::getInstance()->getPreferencesFactory();
- $prefs = $preferencesFactory->getFormDescriptor( $user, $this->getContext() );
+ $prefs = $this->getPreferences();
$prefsKinds = $user->getOptionKinds( $this->getContext(), $changes );
$htmlForm = null;
switch ( $prefsKinds[$key] ) {
case 'registered':
// Regular option.
- if ( $htmlForm === null ) {
- // We need a dummy HTMLForm for the validate callback...
- $htmlForm = new HTMLForm( [], $this );
+ if ( $value === null ) {
+ // Reset it
+ $validation = true;
+ } else {
+ // Validate
+ if ( $htmlForm === null ) {
+ // We need a dummy HTMLForm for the validate callback...
+ $htmlForm = new HTMLForm( [], $this );
+ }
+ $field = HTMLForm::loadInputFromParameters( $key, $prefs[$key], $htmlForm );
+ $validation = $field->validate( $value, $user->getOptions() );
}
- $field = HTMLForm::loadInputFromParameters( $key, $prefs[$key], $htmlForm );
- $validation = $field->validate( $value, $user->getOptions() );
break;
case 'registered-multiselect':
case 'registered-checkmatrix':
break;
}
if ( $validation === true ) {
- $user->setOption( $key, $value );
+ $this->setPreference( $key, $value );
$changed = true;
} else {
$this->addWarning( [ 'apiwarn-validationfailed', wfEscapeWikiText( $key ), $validation ] );
}
if ( $changed ) {
- // Commit changes
- $user->saveSettings();
+ $this->commitChanges();
}
$this->getResult()->addValue( null, $this->getModuleName(), 'success' );
}
+ /**
+ * Load the user from the master to reduce CAS errors on double post (T95839)
+ *
+ * @return null|User
+ */
+ protected function getUserForUpdates() {
+ if ( !$this->userForUpdates ) {
+ $this->userForUpdates = $this->getUser()->getInstanceForUpdate();
+ }
+
+ return $this->userForUpdates;
+ }
+
+ /**
+ * Returns preferences form descriptor
+ * @return mixed[][]
+ */
+ protected function getPreferences() {
+ $preferencesFactory = MediaWikiServices::getInstance()->getPreferencesFactory();
+ return $preferencesFactory->getFormDescriptor( $this->getUserForUpdates(),
+ $this->getContext() );
+ }
+
+ /**
+ * @param string[] $kinds One or more types returned by User::listOptionKinds() or 'all'
+ */
+ protected function resetPreferences( array $kinds ) {
+ $this->getUserForUpdates()->resetOptions( $kinds, $this->getContext() );
+ }
+
+ /**
+ * Sets one user preference to be applied by commitChanges()
+ *
+ * @param string $preference
+ * @param mixed $value
+ */
+ protected function setPreference( $preference, $value ) {
+ $this->getUserForUpdates()->setOption( $preference, $value );
+ }
+
+ /**
+ * Applies changes to user preferences
+ */
+ protected function commitChanges() {
+ $this->getUserForUpdates()->saveSettings();
+ }
+
public function mustBePosted() {
return true;
}