SpecialChangeEmail   A
last analyzed

Complexity

Total Complexity 24

Size/Duplication

Total Lines 156
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 13

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 156
rs 10
wmc 24
lcom 1
cbo 13

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A doesWrites() 0 3 1
A alterForm() 0 8 1
A isListed() 0 3 1
A execute() 0 8 1
B getFormFields() 0 24 2
A getDisplayFormat() 0 3 1
A onSubmit() 0 7 1
B attemptChange() 0 24 5
A requiresUnblock() 0 3 1
A getGroupName() 0 3 1
A checkExecutePermissions() 0 16 3
B onSuccess() 0 20 5
1
<?php
2
/**
3
 * Implements Special:ChangeEmail
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License along
16
 * with this program; if not, write to the Free Software Foundation, Inc.,
17
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
 * http://www.gnu.org/copyleft/gpl.html
19
 *
20
 * @file
21
 * @ingroup SpecialPage
22
 */
23
24
use MediaWiki\Auth\AuthManager;
25
26
/**
27
 * Let users change their email address.
28
 *
29
 * @ingroup SpecialPage
30
 */
31
class SpecialChangeEmail extends FormSpecialPage {
32
	/**
33
	 * @var Status
34
	 */
35
	private $status;
36
37
	public function __construct() {
38
		parent::__construct( 'ChangeEmail', 'editmyprivateinfo' );
39
	}
40
41
	public function doesWrites() {
42
		return true;
43
	}
44
45
	/**
46
	 * @return bool
47
	 */
48
	public function isListed() {
49
		return AuthManager::singleton()->allowsPropertyChange( 'emailaddress' );
50
	}
51
52
	/**
53
	 * Main execution point
54
	 * @param string $par
55
	 */
56
	function execute( $par ) {
57
		$this->checkLoginSecurityLevel();
58
59
		$out = $this->getOutput();
60
		$out->disallowUserJs();
61
62
		parent::execute( $par );
63
	}
64
65
	protected function checkExecutePermissions( User $user ) {
66
67
		if ( !AuthManager::singleton()->allowsPropertyChange( 'emailaddress' ) ) {
68
			throw new ErrorPageError( 'changeemail', 'cannotchangeemail' );
69
		}
70
71
		$this->requireLogin( 'changeemail-no-info' );
72
73
		// This could also let someone check the current email address, so
74
		// require both permissions.
75
		if ( !$this->getUser()->isAllowed( 'viewmyprivateinfo' ) ) {
76
			throw new PermissionsError( 'viewmyprivateinfo' );
77
		}
78
79
		parent::checkExecutePermissions( $user );
80
	}
81
82
	protected function getFormFields() {
83
		$user = $this->getUser();
84
85
		$fields = [
86
			'Name' => [
87
				'type' => 'info',
88
				'label-message' => 'username',
89
				'default' => $user->getName(),
90
			],
91
			'OldEmail' => [
92
				'type' => 'info',
93
				'label-message' => 'changeemail-oldemail',
94
				'default' => $user->getEmail() ?: $this->msg( 'changeemail-none' )->text(),
95
			],
96
			'NewEmail' => [
97
				'type' => 'email',
98
				'label-message' => 'changeemail-newemail',
99
				'autofocus' => true,
100
				'help-message' => 'changeemail-newemail-help',
101
			],
102
		];
103
104
		return $fields;
105
	}
106
107
	protected function getDisplayFormat() {
108
		return 'ooui';
109
	}
110
111
	protected function alterForm( HTMLForm $form ) {
112
		$form->setId( 'mw-changeemail-form' );
113
		$form->setTableId( 'mw-changeemail-table' );
114
		$form->setSubmitTextMsg( 'changeemail-submit' );
115
		$form->addHiddenFields( $this->getRequest()->getValues( 'returnto', 'returntoquery' ) );
116
117
		$form->addHeaderText( $this->msg( 'changeemail-header' )->parseAsBlock() );
118
	}
119
120
	public function onSubmit( array $data ) {
121
		$status = $this->attemptChange( $this->getUser(), $data['NewEmail'] );
122
123
		$this->status = $status;
124
125
		return $status;
126
	}
127
128
	public function onSuccess() {
129
		$request = $this->getRequest();
130
131
		$returnto = $request->getVal( 'returnto' );
132
		$titleObj = $returnto !== null ? Title::newFromText( $returnto ) : null;
133
		if ( !$titleObj instanceof Title ) {
134
			$titleObj = Title::newMainPage();
135
		}
136
		$query = $request->getVal( 'returntoquery' );
137
138
		if ( $this->status->value === true ) {
139
			$this->getOutput()->redirect( $titleObj->getFullURL( $query ) );
140
		} elseif ( $this->status->value === 'eauth' ) {
141
			# Notify user that a confirmation email has been sent...
142
			$this->getOutput()->wrapWikiMsg( "<div class='error' style='clear: both;'>\n$1\n</div>",
143
				'eauthentsent', $this->getUser()->getName() );
144
			// just show the link to go back
145
			$this->getOutput()->addReturnTo( $titleObj, wfCgiToArray( $query ) );
0 ignored issues
show
Bug introduced by
It seems like $titleObj can be null; however, addReturnTo() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
146
		}
147
	}
148
149
	/**
150
	 * @param User $user
151
	 * @param string $newaddr
152
	 * @return Status
153
	 */
154
	private function attemptChange( User $user, $newaddr ) {
155
		$authManager = AuthManager::singleton();
0 ignored issues
show
Unused Code introduced by
$authManager is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
156
157
		if ( $newaddr != '' && !Sanitizer::validateEmail( $newaddr ) ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression \Sanitizer::validateEmail($newaddr) of type null|boolean is loosely compared to false; this is ambiguous if the boolean can be false. You might want to explicitly use !== null instead.

If an expression can have both false, and null as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.

$a = canBeFalseAndNull();

// Instead of
if ( ! $a) { }

// Better use one of the explicit versions:
if ($a !== null) { }
if ($a !== false) { }
if ($a !== null && $a !== false) { }
Loading history...
158
			return Status::newFatal( 'invalidemailaddress' );
159
		}
160
161
		if ( $newaddr === $user->getEmail() ) {
162
			return Status::newFatal( 'changeemail-nochange' );
163
		}
164
165
		$oldaddr = $user->getEmail();
166
		$status = $user->setEmailWithConfirmation( $newaddr );
167
		if ( !$status->isGood() ) {
168
			return $status;
169
		}
170
171
		Hooks::run( 'PrefsEmailAudit', [ $user, $oldaddr, $newaddr ] );
172
173
		$user->saveSettings();
174
		MediaWiki\Auth\AuthManager::callLegacyAuthPlugin( 'updateExternalDB', [ $user ] );
175
176
		return $status;
177
	}
178
179
	public function requiresUnblock() {
180
		return false;
181
	}
182
183
	protected function getGroupName() {
184
		return 'users';
185
	}
186
}
187