MediaWiki  master
ApiOptions.php
Go to the documentation of this file.
1 <?php
24 
31 class ApiOptions extends ApiBase {
33  private $userForUpdates;
34 
38  public function execute() {
39  $user = $this->getUserForUpdates();
40  if ( !$user || $user->isAnon() ) {
41  $this->dieWithError(
42  [ 'apierror-mustbeloggedin', $this->msg( 'action-editmyoptions' ) ], 'notloggedin'
43  );
44  }
45 
46  $this->checkUserRightsAny( 'editmyoptions' );
47 
48  $params = $this->extractRequestParams();
49  $changed = false;
50 
51  if ( isset( $params['optionvalue'] ) && !isset( $params['optionname'] ) ) {
52  $this->dieWithError( [ 'apierror-missingparam', 'optionname' ] );
53  }
54 
55  $resetKinds = $params['resetkinds'];
56  if ( !$params['reset'] ) {
57  $resetKinds = [];
58  }
59 
60  $changes = [];
61  if ( $params['change'] ) {
62  foreach ( $params['change'] as $entry ) {
63  $array = explode( '=', $entry, 2 );
64  $changes[$array[0]] = $array[1] ?? null;
65  }
66  }
67  if ( isset( $params['optionname'] ) ) {
68  $newValue = $params['optionvalue'] ?? null;
69  $changes[$params['optionname']] = $newValue;
70  }
71 
72  $this->getHookRunner()->onApiOptions( $this, $user, $changes, $resetKinds );
73 
74  if ( $resetKinds ) {
75  $this->resetPreferences( $resetKinds );
76  $changed = true;
77  }
78 
79  if ( !$changed && !count( $changes ) ) {
80  $this->dieWithError( 'apierror-nochanges' );
81  }
82 
83  $prefs = $this->getPreferences();
84  $prefsKinds = $user->getOptionKinds( $this->getContext(), $changes );
85 
86  $htmlForm = null;
87  foreach ( $changes as $key => $value ) {
88  switch ( $prefsKinds[$key] ) {
89  case 'registered':
90  // Regular option.
91  if ( $value === null ) {
92  // Reset it
93  $validation = true;
94  } else {
95  // Validate
96  if ( $htmlForm === null ) {
97  // We need a dummy HTMLForm for the validate callback...
98  $htmlForm = new HTMLForm( [], $this );
99  }
100  $field = HTMLForm::loadInputFromParameters( $key, $prefs[$key], $htmlForm );
101  $validation = $field->validate( $value, $user->getOptions() );
102  }
103  break;
104  case 'registered-multiselect':
105  case 'registered-checkmatrix':
106  // A key for a multiselect or checkmatrix option.
107  $validation = true;
108  $value = $value !== null ? (bool)$value : null;
109  break;
110  case 'userjs':
111  // Allow non-default preferences prefixed with 'userjs-', to be set by user scripts
112  if ( strlen( $key ) > 255 ) {
113  $validation = $this->msg( 'apiwarn-validationfailed-keytoolong', Message::numParam( 255 ) );
114  } elseif ( preg_match( '/[^a-zA-Z0-9_-]/', $key ) !== 0 ) {
115  $validation = $this->msg( 'apiwarn-validationfailed-badchars' );
116  } else {
117  $validation = true;
118  }
119  break;
120  case 'special':
121  $validation = $this->msg( 'apiwarn-validationfailed-cannotset' );
122  break;
123  case 'unused':
124  default:
125  $validation = $this->msg( 'apiwarn-validationfailed-badpref' );
126  break;
127  }
128  if ( $validation === true ) {
129  $this->setPreference( $key, $value );
130  $changed = true;
131  } else {
132  $this->addWarning( [ 'apiwarn-validationfailed', wfEscapeWikiText( $key ), $validation ] );
133  }
134  }
135 
136  if ( $changed ) {
137  $this->commitChanges();
138  }
139 
140  $this->getResult()->addValue( null, $this->getModuleName(), 'success' );
141  }
142 
148  protected function getUserForUpdates() {
149  if ( !$this->userForUpdates ) {
150  $this->userForUpdates = $this->getUser()->getInstanceForUpdate();
151  }
152 
153  return $this->userForUpdates;
154  }
155 
160  protected function getPreferences() {
161  $preferencesFactory = MediaWikiServices::getInstance()->getPreferencesFactory();
162  $preferencesFactory->setUser( $this->getUserForUpdates() );
163  // Note that the $user parameter of getFormDescriptor() is deprecated.
164  return $preferencesFactory->getFormDescriptor( $this->getUserForUpdates(),
165  $this->getContext() );
166  }
167 
171  protected function resetPreferences( array $kinds ) {
172  $this->getUserForUpdates()->resetOptions( $kinds, $this->getContext() );
173  }
174 
181  protected function setPreference( $preference, $value ) {
182  $this->getUserForUpdates()->setOption( $preference, $value );
183  }
184 
188  protected function commitChanges() {
189  $this->getUserForUpdates()->saveSettings();
190  }
191 
192  public function mustBePosted() {
193  return true;
194  }
195 
196  public function isWriteMode() {
197  return true;
198  }
199 
200  public function getAllowedParams() {
201  $optionKinds = User::listOptionKinds();
202  $optionKinds[] = 'all';
203 
204  return [
205  'reset' => false,
206  'resetkinds' => [
207  ApiBase::PARAM_TYPE => $optionKinds,
208  ApiBase::PARAM_DFLT => 'all',
210  ],
211  'change' => [
212  ApiBase::PARAM_ISMULTI => true,
213  ],
214  'optionname' => [
215  ApiBase::PARAM_TYPE => 'string',
216  ],
217  'optionvalue' => [
218  ApiBase::PARAM_TYPE => 'string',
219  ],
220  ];
221  }
222 
223  public function needsToken() {
224  return 'csrf';
225  }
226 
227  public function getHelpUrls() {
228  return 'https://www.mediawiki.org/wiki/Special:MyLanguage/API:Options';
229  }
230 
231  protected function getExamplesMessages() {
232  return [
233  'action=options&reset=&token=123ABC'
234  => 'apihelp-options-example-reset',
235  'action=options&change=skin=vector|hideminor=1&token=123ABC'
236  => 'apihelp-options-example-change',
237  'action=options&reset=&change=skin=monobook&optionname=nickname&' .
238  'optionvalue=[[User:Beau|Beau]]%20([[User_talk:Beau|talk]])&token=123ABC'
239  => 'apihelp-options-example-complex',
240  ];
241  }
242 }
Message\numParam
static numParam( $num)
Definition: Message.php:1046
ContextSource\getContext
getContext()
Get the base IContextSource object.
Definition: ContextSource.php:40
ApiBase\addWarning
addWarning( $msg, $code=null, $data=null)
Add a warning for this module.
Definition: ApiBase.php:1334
ApiOptions\getUserForUpdates
getUserForUpdates()
Load the user from the master to reduce CAS errors on double post (T95839)
Definition: ApiOptions.php:148
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:146
ApiOptions\commitChanges
commitChanges()
Applies changes to user preferences.
Definition: ApiOptions.php:188
ApiBase\dieWithError
dieWithError( $msg, $code=null, $data=null, $httpCode=null)
Abort execution with an error.
Definition: ApiBase.php:1415
ApiOptions\isWriteMode
isWriteMode()
Indicates whether this module requires write mode.
Definition: ApiOptions.php:196
true
return true
Definition: router.php:90
ApiOptions\getPreferences
getPreferences()
Returns preferences form descriptor.
Definition: ApiOptions.php:160
ApiBase\PARAM_TYPE
const PARAM_TYPE
(boolean) Inverse of IntegerDef::PARAM_IGNORE_RANGE
Definition: ApiBase.php:68
ApiBase\getResult
getResult()
Get the result object.
Definition: ApiBase.php:546
ApiBase\checkUserRightsAny
checkUserRightsAny( $rights, $user=null)
Helper function for permission-denied errors.
Definition: ApiBase.php:1517
ContextSource\getUser
getUser()
Definition: ContextSource.php:120
ApiBase
This abstract class implements many basic API functions, and is the base of all API classes.
Definition: ApiBase.php:50
ApiOptions\setPreference
setPreference( $preference, $value)
Sets one user preference to be applied by commitChanges()
Definition: ApiOptions.php:181
ApiOptions\getAllowedParams
getAllowedParams()
Returns an array of allowed parameters (parameter name) => (default value) or (parameter name) => (ar...
Definition: ApiOptions.php:200
ApiOptions\execute
execute()
Changes preferences of the current user.
Definition: ApiOptions.php:38
ApiOptions\getExamplesMessages
getExamplesMessages()
Returns usage examples for this module.
Definition: ApiOptions.php:231
ApiOptions\mustBePosted
mustBePosted()
Indicates whether this module must be called with a POST request.
Definition: ApiOptions.php:192
ApiBase\extractRequestParams
extractRequestParams( $options=[])
Using getAllowedParams(), this function makes an array of the values provided by the user,...
Definition: ApiBase.php:695
HTMLForm\loadInputFromParameters
static loadInputFromParameters( $fieldname, $descriptor, HTMLForm $parent=null)
Initialise a new Object for the field.
Definition: HTMLForm.php:516
ContextSource\msg
msg( $key,... $params)
Get a Message object with context set Parameters are the same as wfMessage()
Definition: ContextSource.php:168
ApiOptions
API module that facilitates the changing of user's preferences.
Definition: ApiOptions.php:31
ApiOptions\needsToken
needsToken()
Returns the token type this module requires in order to execute.
Definition: ApiOptions.php:223
wfEscapeWikiText
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking,...
Definition: GlobalFunctions.php:1485
ApiBase\PARAM_DFLT
const PARAM_DFLT
(boolean) Inverse of IntegerDef::PARAM_IGNORE_RANGE
Definition: ApiBase.php:66
ApiBase\getModuleName
getModuleName()
Get the name of the module being executed by this instance.
Definition: ApiBase.php:426
ApiBase\PARAM_ISMULTI
const PARAM_ISMULTI
(boolean) Inverse of IntegerDef::PARAM_IGNORE_RANGE
Definition: ApiBase.php:67
ApiOptions\resetPreferences
resetPreferences(array $kinds)
Definition: ApiOptions.php:171
ApiBase\getHookRunner
getHookRunner()
Get an ApiHookRunner for running core API hooks.
Definition: ApiBase.php:641
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:55
ApiOptions\getHelpUrls
getHelpUrls()
Return links to more detailed help pages about the module.
Definition: ApiOptions.php:227
User\listOptionKinds
static listOptionKinds()
Return a list of the types of user options currently returned by User::getOptionKinds().
Definition: User.php:2890
ApiOptions\$userForUpdates
User $userForUpdates
User account to modify.
Definition: ApiOptions.php:33
HTMLForm
Object handling generic submission, CSRF protection, layout and other logic for UI forms in a reusabl...
Definition: HTMLForm.php:133