diff --git a/includes/specials/SpecialCloseAccount.php b/includes/specials/SpecialCloseAccount.php index 33d1f4d..d5520c1 100644 --- a/includes/specials/SpecialCloseAccount.php +++ b/includes/specials/SpecialCloseAccount.php @@ -11,6 +11,7 @@ * @see https://bugzilla.shoutwiki.com/show_bug.cgi?id=294 */ +use MediaWiki\MediaWikiServices; use MediaWiki\User\UserGroupManager; use MediaWiki\User\UserNameUtils; @@ -18,15 +19,17 @@ class CloseAccount extends EditAccount { /** - * @var User User object for the account that is to be disabled + * @var null|User User object for the account that is to be disabled */ - public $mUser; + public ?User $mUser; - /** @var UserGroupManager */ - private $userGroupManager; + /** + * @var UserGroupManager + */ + private UserGroupManager $userGroupManager; /** @var UserNameUtils */ - private $userNameUtils; + private UserNameUtils $userNameUtils; /** * Constructor -- set up the new special page @@ -48,7 +51,7 @@ public function __construct( * * @return string */ - public function getGroupName() { + public function getGroupName(): string { return 'users'; } @@ -57,7 +60,7 @@ public function getGroupName() { * * @return string Special page description */ - public function getDescription() { + public function getDescription(): string { return $this->msg( 'editaccount-general-description' )->plain(); } @@ -67,7 +70,7 @@ public function getDescription() { * * @return bool */ - public function isListed() { + public function isListed(): bool { $user = $this->getUser(); $effectiveGroups = $this->userGroupManager->getUserEffectiveGroups( $user ); $isStaff = in_array( 'staff', $effectiveGroups ); @@ -77,9 +80,9 @@ public function isListed() { /** * Show the special page * - * @param string|null $par Parameter (user name) passed to the page or null + * @param string|null $subPage Parameter (user name) passed to the page or null */ - public function execute( $par ) { + public function execute( $subPage ) { $out = $this->getOutput(); $request = $this->getRequest(); $user = $this->getUser(); @@ -119,7 +122,7 @@ public function execute( $par ) { // Check if user name is an existing user if ( $this->userNameUtils->isValid( $userName ) ) { - $this->mUser = User::newFromName( $userName ); + $this->mUser = MediaWikiServices::getInstance()->getUserFactory()->newFromName( $userName ); } $changeReason = $request->getVal( 'wpReason' ); @@ -135,7 +138,7 @@ public function execute( $par ) { $out->addHTML( "
\n" . $this->msg( 'editaccount-status' )->escaped() . '' . - Xml::element( 'span', [ 'style' => "color: {$color}; font-weight: bold;" ], $this->mStatusMsg ) . + Xml::element( 'span', [ 'style' => "color: $color; font-weight: bold;" ], $this->mStatusMsg ) . '
' ); } else { diff --git a/includes/specials/SpecialEditAccount.php b/includes/specials/SpecialEditAccount.php index 4b3a994..b4fac87 100644 --- a/includes/specials/SpecialEditAccount.php +++ b/includes/specials/SpecialEditAccount.php @@ -1,8 +1,8 @@ passwordFactory = $passwordFactory; $this->userNameUtils = $userNameUtils; $this->userOptionsManager = $userOptionsManager; - $this->cache = $cache; } - public function doesWrites() { + public function doesWrites(): bool { return true; } @@ -68,7 +62,7 @@ public function doesWrites() { * * @return string */ - public function getGroupName() { + public function getGroupName(): string { return 'users'; } @@ -78,7 +72,7 @@ public function getGroupName() { * * @return string Special page description */ - public function getDescription() { + public function getDescription(): string { if ( $this->getUser()->isAllowed( 'editaccount' ) ) { return $this->msg( 'editaccount' )->plain(); } else { @@ -89,12 +83,13 @@ public function getDescription() { /** * Show the special page * - * @param string|null $par Parameter (user name) passed to the page or null + * @param string|null $subPage Parameter (user name) passed to the page or null */ - public function execute( $par ) { + public function execute( $subPage ) { $out = $this->getOutput(); $request = $this->getRequest(); $user = $this->getUser(); + $services = MediaWikiServices::getInstance(); // Redirect mortals to Special:CloseAccount if ( !$user->isAllowed( 'editaccount' ) ) { @@ -118,7 +113,7 @@ public function execute( $par ) { $out->setPageTitle( $this->getDescription() ); // Get name to work on. Subpage is supported, but form submit name trumps - $userName = $request->getVal( 'wpUserName', $par ); + $userName = $request->getVal( 'wpUserName', $subPage ); $action = $request->getVal( 'wpAction' ); if ( $userName !== null ) { @@ -129,8 +124,10 @@ public function execute( $par ) { // Check if user name is an existing user if ( $this->userNameUtils->isValid( $userName ) ) { - $this->mUser = User::newFromName( $userName ); - $id = $this->mUser->idFromName( $userName ); + $userFactory = $services->getUserFactory(); + $this->mUser = $userFactory->newFromName( $userName ); + $actor = $services->getUserIdentityLookup()->getUserIdentityByName( $userName ); + $id = $actor ? $actor->getId() : null; if ( empty( $action ) ) { $action = 'displayuser'; @@ -144,7 +141,7 @@ public function execute( $par ) { if ( $this->mTempUser ) { $id = $this->mTempUser->getId(); - $this->mUser = User::newFromId( $id ); + $this->mUser = $userFactory->newFromId( $id ); } else { $this->mStatus = false; $this->mStatusMsg = $this->msg( 'editaccount-nouser', $userName )->text(); @@ -216,6 +213,7 @@ public function execute( $par ) { $templateClassName = 'EditAccount' . $template . 'Template'; $tmpl = new $templateClassName; + $linkRenderer = $services->getLinkRenderer(); $templateVariables = [ 'status' => $this->mStatus, 'statusMsg' => $this->mStatusMsg, @@ -231,9 +229,9 @@ public function execute( $par ) { 'isDisabled' => null, 'isAdopter' => null, 'returnURL' => $this->getFullTitle()->getFullURL(), - 'logLink' => Linker::linkKnown( + 'logLink' => $linkRenderer->makeLink( SpecialPage::getTitleFor( 'Log', 'editaccnt' ), - $this->msg( 'log-name-editaccnt' )->escaped() + $this->msg( 'log-name-editaccnt' ) ), 'userStatus' => null, 'emailStatus' => null, @@ -298,8 +296,7 @@ public function execute( $par ) { * @param string $changeReason Reason for change * @return bool True on success, false on failure (i.e. if we were given an invalid email address) */ - public function setEmail( $email, $changeReason = '' ) { - $oldEmail = $this->mUser->getEmail(); + public function setEmail( string $email, string $changeReason = '' ): bool { if ( Sanitizer::validateEmail( $email ) || $email == '' ) { if ( $this->mTempUser ) { if ( $email == '' ) { @@ -331,7 +328,7 @@ public function setEmail( $email, $changeReason = '' ) { $logEntry->setTarget( $this->mUser->getUserPage() ); // JP 13 April 2013: not sure if this is the correct one, CHECKME $logEntry->setComment( $changeReason ); - $logId = $logEntry->insert(); + $logEntry->insert(); if ( $email == '' ) { $this->mStatusMsg = $this->msg( 'editaccount-success-email-blank', $this->mUser->mName )->text(); @@ -356,7 +353,7 @@ public function setEmail( $email, $changeReason = '' ) { * @param string $changeReason Reason for change * @return bool True on success, false on failure */ - public function setPassword( $pass, $changeReason = '' ) { + public function setPassword( $pass, string $changeReason = '' ): bool { if ( $this->setPasswordForUser( $this->mUser, $pass ) ) { // Save the new settings if ( $this->mTempUser ) { @@ -374,7 +371,7 @@ public function setPassword( $pass, $changeReason = '' ) { $logEntry->setTarget( $this->mUser->getUserPage() ); // JP 13 April 2013: not sure if this is the correct one, CHECKME $logEntry->setComment( $changeReason ); - $logId = $logEntry->insert(); + $logEntry->insert(); // And finally, inform the user that everything went as planned $this->mStatusMsg = $this->msg( 'editaccount-success-pass', $this->mUser->mName )->text(); @@ -393,13 +390,13 @@ public function setPassword( $pass, $changeReason = '' ) { * @param string $password * @return bool */ - public function setPasswordForUser( User $user, $password ) { + public function setPasswordForUser( User $user, string $password ): bool { if ( !$user->getId() ) { return false; // throw new MWException( "Passed User has not been added to the database yet!" ); } - $dbw = wfGetDB( DB_PRIMARY ); + $dbw = MediaWikiServices::getInstance()->getDBLoadBalancer()->getMaintenanceConnectionRef( DB_PRIMARY ); $row = $dbw->selectRow( 'user', 'user_id', @@ -429,7 +426,7 @@ public function setPasswordForUser( User $user, $password ) { * @param string $changeReason Reason for change * @return bool True on success, false on failure */ - public function setRealName( $realName, $changeReason = '' ) { + public function setRealName( $realName, string $changeReason = '' ): bool { $this->mUser->setRealName( $realName ); $this->mUser->saveSettings(); @@ -442,7 +439,7 @@ public function setRealName( $realName, $changeReason = '' ) { $logEntry->setTarget( $this->mUser->getUserPage() ); // JP 13 April 2013: not sure if this is the correct one, CHECKME $logEntry->setComment( $changeReason ); - $logId = $logEntry->insert(); + $logEntry->insert(); // And finally, inform the user that everything went as planned $this->mStatusMsg = $this->msg( 'editaccount-success-realname', $this->mUser->mName )->text(); @@ -461,7 +458,7 @@ public function setRealName( $realName, $changeReason = '' ) { * @param string $changeReason Reason for change * @return bool True on success, false on failure */ - public function closeAccount( $changeReason = '' ) { + public function closeAccount( string $changeReason = '' ): bool { // Set flag for Special:Contributions // NOTE: requires FlagClosedAccounts.php to be included separately if ( defined( 'CLOSED_ACCOUNT_FLAG' ) ) { @@ -472,15 +469,7 @@ public function closeAccount( $changeReason = '' ) { $this->mUser->setRealName( '' ); } - // remove user's avatar - if ( class_exists( 'wAvatar' ) ) { - // SocialProfile - // Commented out because as of 17 June 2013, ShoutWiki has only 8 - // wikis with SocialProfile enabled and this method is probably - // *very* expensive since it does operations for everything in the - // images directory... - //$this->removeSocialProfileAvatars(); - } elseif ( class_exists( 'Masthead' ) ) { + if ( class_exists( 'Masthead' ) ) { // Wikia's avatar extension $avatar = Masthead::newFromUser( $this->mUser ); if ( !$avatar->isDefault() ) { @@ -503,7 +492,7 @@ public function closeAccount( $changeReason = '' ) { $id = $this->mUser->getId(); // Reload user - $this->mUser = User::newFromId( $id ); + $this->mUser = MediaWikiServices::getInstance()->getUserFactory()->newFromId( $id ); if ( $this->mUser->getEmail() == '' ) { // ShoutWiki patch begin @@ -528,7 +517,7 @@ public function closeAccount( $changeReason = '' ) { $logEntry->setTarget( $this->mUser->getUserPage() ); // JP 13 April 2013: not sure if this is the correct one, CHECKME $logEntry->setComment( $changeReason ); - $logId = $logEntry->insert(); + $logEntry->insert(); // All clear! $this->mStatusMsg = $this->msg( 'editaccount-success-close', $this->mUser->mName )->text(); @@ -545,7 +534,7 @@ public function closeAccount( $changeReason = '' ) { * * @return bool Always true */ - public function clearUnsubscribe() { + public function clearUnsubscribe(): bool { $this->userOptionsManager->setOption( $this->mUser, 'unsubscribed', null ); $this->userOptionsManager->saveOptions( $this->mUser ); @@ -559,7 +548,7 @@ public function clearUnsubscribe() { * * @return bool Always true */ - public function clearDisable() { + public function clearDisable(): bool { $this->userOptionsManager->setOption( $this->mUser, 'disabled', null ); $this->userOptionsManager->setOption( $this->mUser, 'disabled_date', null ); $this->userOptionsManager->saveOptions( $this->mUser ); @@ -605,7 +594,7 @@ public function clearDisable() { * * @return bool Always true */ - public function toggleAdopterStatus() { + public function toggleAdopterStatus(): bool { $this->userOptionsManager->setOption( $this->mUser, 'AllowAdoption', @@ -624,7 +613,7 @@ public function toggleAdopterStatus() { * * @return string */ - public function generateRandomScrambledPassword() { + public function generateRandomScrambledPassword(): string { // Password requirements need a capital letter, a digit, and a lowercase letter. // wfGenerateToken() returns a 32 char hex string, which will almost // always satisfy the digit/letter but not always. @@ -634,132 +623,6 @@ public function generateRandomScrambledPassword() { return ( self::generateToken() . $REQUIRED_CHARS ); } - /** - * Remove SocialProfile avatars from all wikis. - * - * @note The foreach loop is almost a verbatim copy-paste of the private method - * RemoveAvatar::deleteImage() from extensions/SocialProfile/UserProfile/SpecialRemoveAvatar.php - * That method should be made public and this should then be rewritten - * accordingly. - * - * @return bool Always true - */ - public function removeSocialProfileAvatars() { - // phpcs:ignore MediaWiki.NamingConventions.ValidGlobalName.allowedPrefix - global $IP, $wgUploadAvatarInRecentChanges; - - // @see http://www.developerfusion.com/code/2058/determine-execution-time-in-php/ - $mtime = microtime(); - $mtime = explode( ' ', $mtime ); - $mtime = $mtime[1] + $mtime[0]; - $startTime = $mtime; - - // @todo FIXME: horribly ShoutWiki-specific - $path = $IP . '/images/'; - $handle = opendir( $path ); - if ( $handle ) { - $file = readdir( $handle ); - while ( $file !== false ) { - // do something with the file - // note that '.' and '..' is returned even - if ( $file != '.' && $file != '..' ) { - $fullpath = $path . $file; - // If this is a directory... - if ( is_dir( $fullpath ) ) { - // change our current working directory to it, then! - chdir( $fullpath ); - // Look for the avatars directory - if ( is_dir( getcwd() . '/avatars' ) ) { - // Split the current directory name from right to left - // @see http://stackoverflow.com/questions/717328/how-to-explode-string-right-to-left - $result = array_map( 'strrev', explode( '/', strrev( getcwd() ) ) ); - // $result[0] should now hold the image directory - // name, from which we can construct the DB name - // easily - if ( isset( $result[0] ) && $result[0] ) { - // Oh fuck, the directory name contains a - // period (i.e. "fi.starwars") - if ( strpos( $result[0], '.' ) !== false ) { - $splitDirName = explode( '.', $result[0] ); - // for fi.starwars, this would look like "starwars_fiwiki" - // which is the expected result. - // Phew, finally! - $dbName = $splitDirName[1] . '_' . $splitDirName[0] . '_wiki'; - } else { - // Just append "_wiki" to the image dir - // name to get the DB name. - $dbName = $result[0] . '_wiki'; - } - // Normalization... - $dbName = str_replace( '-', '_', $dbName ); - - // ACTUALLY REMOVE THE DAMN THINGS! - foreach ( [ 's', 'm', 'ml', 'l' ] as $size ) { - $avatar = new wAvatar( $this->mUser->getId(), $size ); - $files = glob( - getcwd() . '/avatars/' . $dbName . '_' . - $this->mUser->getId() . '_' . $size . '*' - ); - AtEase::suppressWarnings(); - $img = basename( $files[0] ); - AtEase::restoreWarnings(); - if ( $img && $img[0] ) { - unlink( getcwd() . '/avatars/' . $img ); - } - - // clear cache - $key = $this->cache->makeKey( 'user', 'profile', 'avatar', $this->mUser->getId(), $size ); - $this->cache->delete( $key ); - } - - // Ensure that the logs are placed into the correct DB - $dbw = wfGetDB( DB_PRIMARY, [], $dbName ); - // Log it! - // Note: old-school logging style is - // intentionally used here because it's what - // SocialProfile uses, too. - $log = new LogPage( 'avatar' ); - if ( !$wgUploadAvatarInRecentChanges ) { - $log->updateRecentChanges = false; - } - - $logMsg = $this->msg( - 'user-profile-picture-log-delete-entry', - $this->mUser->getName() - ); - // It should never be empty or disabled, but... - if ( !$logMsg->isEmpty() || !$logMsg->isDisabled() ) { - // @phan-suppress-next-line PhanParamTooFew - $log->addEntry( - 'avatar', - $this->getUser()->getUserPage(), - $logMsg->text() - ); - } - } - } else { - // error_log( getcwd() . '/avatars/ does not exist, skipping.' ); - } - } - } - } - closedir( $handle ); - } - - $mtime = microtime(); - $mtime = explode( ' ', $mtime ); - $mtime = $mtime[1] + $mtime[0]; - $endTime = $mtime; - $totalTime = ( $endTime - $startTime ); - - error_log( - __METHOD__ . ': checking for (and possibly deleting) avatars took ' . - $totalTime - ); - - return true; - } - /** * Marks the account as disabled, the ShoutWiki way. */ @@ -798,7 +661,7 @@ public function setDisabled() { * @param User $user * @return bool|void True if it is disabled, otherwise false */ - public static function isAccountDisabled( $user ) { + public static function isAccountDisabled( User $user ) { if ( !class_exists( 'GlobalPreferences' ) ) { error_log( 'Cannot use the GlobalPreferences class in ' . __METHOD__ ); return; @@ -824,7 +687,7 @@ public static function isAccountDisabled( $user ) { * @param string $salt * @return string */ - public static function generateToken( $salt = '' ) { + public static function generateToken( string $salt = '' ): string { $salt = serialize( $salt ); return md5( mt_rand( 0, 0x7fffffff ) . $salt ); } diff --git a/maintenance/setDisabledFlag.php b/maintenance/setDisabledFlag.php index c229cbd..da9078a 100644 --- a/maintenance/setDisabledFlag.php +++ b/maintenance/setDisabledFlag.php @@ -19,6 +19,9 @@ * $IP/extensions/EditAccount and we don't need to move this file to * $IP/maintenance/. */ + +use MediaWiki\MediaWikiServices; + ini_set( 'include_path', __DIR__ . '/../../../maintenance' ); require_once 'Maintenance.php'; @@ -26,14 +29,19 @@ class AddEntriesForAllDisabledUsers extends Maintenance { public function __construct() { parent::__construct(); - $this->mDescription = 'Updates global preferences for accounts that have their real name set to "Account Disabled".'; + $this->addDescription( 'Updates global preferences for accounts that have their real name set to "Account Disabled".' ); $this->addOption( 'doit', 'Actually perform the database updates, too, instead of doing a dry run?' ); $this->requireExtension( 'EditAccount' ); } public function execute() { - $dbw = wfGetDB( DB_PRIMARY ); + if ( !class_exists( 'GlobalPreferences' ) ) { + $this->error( 'This script requires the GlobalPreferences extension to be installed' ); + return; + } + + $dbw = MediaWikiServices::getInstance()->getDBLoadBalancer()->getMaintenanceConnectionRef( DB_PRIMARY ); $res = $dbw->select( 'user', [ 'user_id', 'user_name' ], @@ -51,7 +59,7 @@ public function execute() { foreach ( $res as $row ) { // Are we in it for real? if ( $this->getOption( 'doit' ) ) { - $res = $dbw->update( + $dbw->update( 'global_preferences', [ 'gp_property' => 'disabled', @@ -63,7 +71,7 @@ public function execute() { __METHOD__ ); - $res = $dbw->update( + $dbw->update( 'global_preferences', [ 'gp_property' => 'disabled_date', @@ -76,7 +84,7 @@ public function execute() { ); } - $this->output( "Marked {$row->user_name} (UID: {$row->user_id}) as disabled\n" ); + $this->output( "Marked $row->user_name (UID: $row->user_id) as disabled\n" ); } }