31 private UserFactory $userFactory;
32 private UserNameUtils $userNameUtils;
33 private UserOptionsManager $userOptionsManager;
34 private WikiPageFactory $wikiPageFactory;
35 private UserOptionsLookup $userOptionsLookup;
37 private bool $isSandboxEnabled;
38 public const CONSTRUCTOR_OPTIONS = [
39 'TranslateUseSandbox',
42 public function __construct(
45 UserFactory $userFactory,
46 UserNameUtils $userNameUtils,
47 UserOptionsManager $userOptionsManager,
48 WikiPageFactory $wikiPageFactory,
49 UserOptionsLookup $userOptionsLookup,
51 ServiceOptions $options
53 parent::__construct( $mainModule, $moduleName );
54 $this->userFactory = $userFactory;
55 $this->userNameUtils = $userNameUtils;
56 $this->userOptionsManager = $userOptionsManager;
57 $this->wikiPageFactory = $wikiPageFactory;
58 $this->userOptionsLookup = $userOptionsLookup;
59 $this->translateSandbox = $translateSandbox;
60 $options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
61 $this->isSandboxEnabled = $options->get(
'TranslateUseSandbox' );
64 public function execute():
void {
65 if ( !$this->isSandboxEnabled ) {
66 $this->dieWithError(
'apierror-translate-sandboxdisabled',
'sandboxdisabled' );
69 $params = $this->extractRequestParams();
70 switch ( $params[
'do'] ) {
84 $this->dieWithError( [
'apierror-badparameter',
'do' ] );
88 private function doCreate():
void {
89 $params = $this->extractRequestParams();
92 foreach ( explode(
'|',
'username|password|email' ) as $field ) {
93 if ( !isset( $params[$field] ) ) {
94 $this->dieWithError( [
'apierror-missingparam', $field ],
'missingparam' );
98 $username = $params[
'username'];
100 $canonicalName = $this->userNameUtils->getCanonical( $username, UserNameUtils::RIGOR_CREATABLE );
102 if ( $canonicalName ===
false ) {
103 $this->dieWithError(
'noname',
'invalidusername' );
106 $user = $this->userFactory->newFromName( $username );
107 if ( $user->getId() !== 0 ) {
108 $this->dieWithError(
'userexists',
'nonfreeusername' );
111 $password = $params[
'password'];
112 $passwordValidityStatus = $user->checkPasswordValidity( $password );
113 if ( !$passwordValidityStatus->isGood() ) {
114 $this->dieStatus( $passwordValidityStatus );
117 $email = $params[
'email'];
118 if ( !Sanitizer::validateEmail( $email ) ) {
119 $this->dieWithError(
'invalidemailaddress',
'invalidemail' );
123 $user = $this->translateSandbox->addUser( $username, $email, $password );
124 }
catch ( RuntimeException $e ) {
127 $this->dieWithError(
'apierror-translate-sandbox-user-add' );
133 $output = [
'user' => [
134 'name' => $user->getName(),
135 'id' => $user->getId(),
138 $this->userOptionsManager->setOption( $user,
'language', $this->getContext()->getLanguage()->getCode() );
139 $this->userOptionsManager->saveOptions( $user );
141 $this->getResult()->addValue(
null, $this->getModuleName(), $output );
144 private function doDelete():
void {
145 $this->checkUserRightsAny(
'translate-sandboxmanage' );
147 $params = $this->extractRequestParams();
149 foreach ( $params[
'userid'] as $userId ) {
150 $user = $this->userFactory->newFromId( $userId );
151 $userPage = $user->getUserPage();
153 $this->translateSandbox->sendEmail( $this->getUser(), $user,
'rejection' );
156 $this->translateSandbox->deleteUser( $user );
159 [
'apierror-translate-sandbox-invalidparam', wfEscapeWikiText( $e->getMessage() ) ],
164 $logEntry =
new ManualLogEntry(
'translatorsandbox',
'rejected' );
165 $logEntry->setPerformer( $this->getUser() );
166 $logEntry->setTarget( $userPage );
167 $logId = $logEntry->insert();
168 $logEntry->publish( $logId );
172 private function doPromote():
void {
173 $this->checkUserRightsAny(
'translate-sandboxmanage' );
175 $params = $this->extractRequestParams();
177 foreach ( $params[
'userid'] as $userId ) {
178 $user = $this->userFactory->newFromId( $userId );
181 $this->translateSandbox->promoteUser( $user );
184 [
'apierror-translate-sandbox-invalidparam', wfEscapeWikiText( $e->getMessage() ) ],
189 $this->translateSandbox->sendEmail( $this->getUser(), $user,
'promotion' );
191 $logEntry =
new ManualLogEntry(
'translatorsandbox',
'promoted' );
192 $logEntry->setPerformer( $this->getUser() );
193 $logEntry->setTarget( $user->getUserPage() );
194 $logEntry->setParameters( [
195 '4::userid' => $user->getId(),
197 $logId = $logEntry->insert();
198 $logEntry->publish( $logId );
200 $this->createUserPage( $user );
204 private function doRemind():
void {
205 $params = $this->extractRequestParams();
207 foreach ( $params[
'userid'] as $userId ) {
208 $target = $this->userFactory->newFromId( $userId );
211 $this->translateSandbox->sendEmail( $this->getUser(), $target,
'reminder' );
214 [
'apierror-translate-sandbox-invalidparam', wfEscapeWikiText( $e->getMessage() ) ],
222 private function createUserPage( User $user ):
void {
223 $userPage = $user->getUserPage();
225 if ( $userPage->exists() ) {
229 $languagePreferences = FormatJson::decode(
230 $this->userOptionsLookup->getOption( $user,
'translate-sandbox' ),
233 $languages = implode(
'|', $languagePreferences[
'languages' ] ?? [] );
234 $babelText =
"{{#babel:$languages}}";
235 $summary = $this->msg(
'tsb-create-user-page' )->inContentLanguage()->text();
237 $page = $this->wikiPageFactory->newFromTitle( $userPage );
238 $content = ContentHandler::makeContent( $babelText, $userPage );
240 $page->newPageUpdater( $user )
241 ->setContent( SlotRecord::MAIN, $content )
242 ->saveRevision( CommentStoreComment::newUnsavedComment( trim( $summary ) ), EDIT_NEW );
245 public function isWriteMode():
bool {
249 public function needsToken():
string {
253 protected function getAllowedParams(): array {
256 ParamValidator::PARAM_TYPE => [
'create',
'delete',
'promote',
'remind' ],
257 ParamValidator::PARAM_REQUIRED =>
true,
260 ParamValidator::PARAM_TYPE =>
'integer',
261 ParamValidator::PARAM_DEFAULT => 0,
262 ParamValidator::PARAM_ISMULTI =>
true,
264 'username' => [ ParamValidator::PARAM_TYPE =>
'string' ],
265 'password' => [ ParamValidator::PARAM_TYPE =>
'string' ],
266 'email' => [ ParamValidator::PARAM_TYPE =>
'string' ],