MediaWiki REL1_35
SpecialChangeEmail.php
Go to the documentation of this file.
1<?php
26
36 private $status;
37
38 public function __construct() {
39 parent::__construct( 'ChangeEmail', 'editmyprivateinfo' );
40 }
41
42 public function doesWrites() {
43 return true;
44 }
45
49 public function isListed() {
50 return MediaWikiServices::getInstance()->getAuthManager()
51 ->allowsPropertyChange( 'emailaddress' );
52 }
53
58 public function execute( $par ) {
59 $out = $this->getOutput();
60 $out->disallowUserJs();
61
62 parent::execute( $par );
63 }
64
65 protected function getLoginSecurityLevel() {
66 return $this->getName();
67 }
68
69 protected function checkExecutePermissions( User $user ) {
70 $services = MediaWikiServices::getInstance();
71 if ( !$services->getAuthManager()->allowsPropertyChange( 'emailaddress' ) ) {
72 throw new ErrorPageError( 'changeemail', 'cannotchangeemail' );
73 }
74
75 $this->requireLogin( 'changeemail-no-info' );
76
77 // This could also let someone check the current email address, so
78 // require both permissions.
79 if ( !$services->getPermissionManager()
80 ->userHasRight( $this->getUser(), 'viewmyprivateinfo' )
81 ) {
82 throw new PermissionsError( 'viewmyprivateinfo' );
83 }
84
85 parent::checkExecutePermissions( $user );
86 }
87
88 protected function getFormFields() {
89 $user = $this->getUser();
90
91 $fields = [
92 'Name' => [
93 'type' => 'info',
94 'label-message' => 'username',
95 'default' => $user->getName(),
96 ],
97 'OldEmail' => [
98 'type' => 'info',
99 'label-message' => 'changeemail-oldemail',
100 'default' => $user->getEmail() ?: $this->msg( 'changeemail-none' )->text(),
101 ],
102 'NewEmail' => [
103 'type' => 'email',
104 'label-message' => 'changeemail-newemail',
105 'autofocus' => true,
106 'maxlength' => 255,
107 'help-message' => 'changeemail-newemail-help',
108 ],
109 ];
110
111 return $fields;
112 }
113
114 protected function getDisplayFormat() {
115 return 'ooui';
116 }
117
118 protected function alterForm( HTMLForm $form ) {
119 $form->setId( 'mw-changeemail-form' );
120 $form->setTableId( 'mw-changeemail-table' );
121 $form->setSubmitTextMsg( 'changeemail-submit' );
122 $form->addHiddenFields( $this->getRequest()->getValues( 'returnto', 'returntoquery' ) );
123
124 $form->addHeaderText( $this->msg( 'changeemail-header' )->parseAsBlock() );
125 }
126
127 public function onSubmit( array $data ) {
128 $status = $this->attemptChange( $this->getUser(), $data['NewEmail'] );
129
130 $this->status = $status;
131
132 return $status;
133 }
134
135 public function onSuccess() {
136 $request = $this->getRequest();
137
138 $returnto = $request->getVal( 'returnto' );
139 $titleObj = $returnto !== null ? Title::newFromText( $returnto ) : null;
140 if ( !$titleObj instanceof Title ) {
141 $titleObj = Title::newMainPage();
142 }
143 $query = $request->getVal( 'returntoquery', '' );
144
145 if ( $this->status->value === true ) {
146 $this->getOutput()->redirect( $titleObj->getFullUrlForRedirect( $query ) );
147 } elseif ( $this->status->value === 'eauth' ) {
148 # Notify user that a confirmation email has been sent...
149 $this->getOutput()->wrapWikiMsg( "<div class='error' style='clear: both;'>\n$1\n</div>",
150 'eauthentsent', $this->getUser()->getName() );
151 // just show the link to go back
152 $this->getOutput()->addReturnTo( $titleObj, wfCgiToArray( $query ) );
153 }
154 }
155
161 private function attemptChange( User $user, $newaddr ) {
162 if ( $newaddr != '' && !Sanitizer::validateEmail( $newaddr ) ) {
163 return Status::newFatal( 'invalidemailaddress' );
164 }
165
166 $oldaddr = $user->getEmail();
167 if ( $newaddr === $oldaddr ) {
168 return Status::newFatal( 'changeemail-nochange' );
169 }
170
171 if ( strlen( $newaddr ) > 255 ) {
172 return Status::newFatal( 'changeemail-maxlength' );
173 }
174
175 // To prevent spam, rate limit adding a new address, but do
176 // not rate limit removing an address.
177 if ( $newaddr !== '' && $user->pingLimiter( 'changeemail' ) ) {
178 return Status::newFatal( 'actionthrottledtext' );
179 }
180
181 $userLatest = $user->getInstanceForUpdate();
182 $status = $userLatest->setEmailWithConfirmation( $newaddr );
183 if ( !$status->isGood() ) {
184 return $status;
185 }
186
187 LoggerFactory::getInstance( 'authentication' )->info(
188 'Changing email address for {user} from {oldemail} to {newemail}', [
189 'user' => $userLatest->getName(),
190 'oldemail' => $oldaddr,
191 'newemail' => $newaddr,
192 ]
193 );
194
195 $this->getHookRunner()->onPrefsEmailAudit( $userLatest, $oldaddr, $newaddr );
196
197 $userLatest->saveSettings();
198
199 return $status;
200 }
201
202 public function requiresUnblock() {
203 return false;
204 }
205
206 protected function getGroupName() {
207 return 'users';
208 }
209}
wfCgiToArray( $query)
This is the logical opposite of wfArrayToCgi(): it accepts a query string as its argument and returns...
An error page which can definitely be safely rendered using the OutputPage.
Special page which uses an HTMLForm to handle processing.
string null $par
The sub-page of the special page.
Object handling generic submission, CSRF protection, layout and other logic for UI forms in a reusabl...
Definition HTMLForm.php:135
setTableId( $id)
Set the id of the <table> or outermost <div> element.
setSubmitTextMsg( $msg)
Set the text for the submit button to a message.
setId( $id)
addHeaderText( $msg, $section=null)
Add HTML to the header, inside the form.
Definition HTMLForm.php:819
addHiddenFields(array $fields)
Add an array of hidden fields to the output.
Definition HTMLForm.php:974
PSR-3 logger instance factory.
MediaWikiServices is the service locator for the application scope of MediaWiki.
Show an error when a user tries to do something they do not have the necessary permissions for.
Let users change their email address.
doesWrites()
Indicates whether this special page may perform database writes.
requiresUnblock()
Whether this action cannot be executed by a blocked user.
getDisplayFormat()
Get display format for the form.
onSuccess()
Do something exciting on successful processing of the form, most likely to show a confirmation messag...
alterForm(HTMLForm $form)
Play with the HTMLForm if you need to more substantially.
getFormFields()
Get an HTMLForm descriptor array.
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
attemptChange(User $user, $newaddr)
checkExecutePermissions(User $user)
Called from execute() to check if the given user can perform this action.
execute( $par)
Main execution point.
getLoginSecurityLevel()
Tells if the special page does something security-sensitive and needs extra defense against a stolen ...
onSubmit(array $data)
Process the form on POST submission.
getName()
Get the name of this Special Page.
getOutput()
Get the OutputPage being used for this instance.
requireLogin( $reasonMsg='exception-nologin-text', $titleMsg='exception-nologin')
If the user is not logged in, throws UserNotLoggedIn error.
getUser()
Shortcut to get the User executing this instance.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getRequest()
Get the WebRequest being used for this instance.
isGood()
Returns whether the operation completed and didn't have any error or warnings.
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition Status.php:44
Represents a title within MediaWiki.
Definition Title.php:42
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition User.php:60
pingLimiter( $action='edit', $incrBy=1)
Primitive rate limits: enforce maximum actions per time period to put a brake on flooding.
Definition User.php:1747
getEmail()
Get the user's e-mail address.
Definition User.php:2545
getInstanceForUpdate()
Get a new instance of this user that was loaded from the master via a locking read.
Definition User.php:4563