MediaWiki  master
SpecialEmailUser.php
Go to the documentation of this file.
1 <?php
28 
35  protected $mTarget;
36 
40  protected $mTargetObj;
41 
43  private $userNameUtils;
44 
46  private $userNamePrefixSearch;
47 
49  private $userOptionsLookup;
50 
56  public function __construct(
57  UserNameUtils $userNameUtils,
58  UserNamePrefixSearch $userNamePrefixSearch,
59  UserOptionsLookup $userOptionsLookup
60  ) {
61  parent::__construct( 'Emailuser' );
62  $this->userNameUtils = $userNameUtils;
63  $this->userNamePrefixSearch = $userNamePrefixSearch;
64  $this->userOptionsLookup = $userOptionsLookup;
65  }
66 
67  public function doesWrites() {
68  return true;
69  }
70 
71  public function getDescription() {
72  $target = self::getTarget( $this->mTarget, $this->getUser() );
73  if ( !$target instanceof User ) {
74  return $this->msg( 'emailuser-title-notarget' )->text();
75  }
76 
77  return $this->msg( 'emailuser-title-target', $target->getName() )->text();
78  }
79 
80  protected function getFormFields() {
81  $linkRenderer = $this->getLinkRenderer();
82  $user = $this->getUser();
83  return [
84  'From' => [
85  'type' => 'info',
86  'raw' => 1,
87  'default' => $linkRenderer->makeLink(
88  $user->getUserPage(),
89  $user->getName()
90  ),
91  'label-message' => 'emailfrom',
92  'id' => 'mw-emailuser-sender',
93  ],
94  'To' => [
95  'type' => 'info',
96  'raw' => 1,
97  'default' => $linkRenderer->makeLink(
98  $this->mTargetObj->getUserPage(),
99  $this->mTargetObj->getName()
100  ),
101  'label-message' => 'emailto',
102  'id' => 'mw-emailuser-recipient',
103  ],
104  'Target' => [
105  'type' => 'hidden',
106  'default' => $this->mTargetObj->getName(),
107  ],
108  'Subject' => [
109  'type' => 'text',
110  'default' => $this->msg( 'defemailsubject', $user->getName() )->inContentLanguage()->text(),
111  'label-message' => 'emailsubject',
112  'maxlength' => 200,
113  'size' => 60,
114  'required' => true,
115  ],
116  'Text' => [
117  'type' => 'textarea',
118  'rows' => 20,
119  'label-message' => 'emailmessage',
120  'required' => true,
121  ],
122  'CCMe' => [
123  'type' => 'check',
124  'label-message' => 'emailccme',
125  'default' => $this->userOptionsLookup->getBoolOption( $user, 'ccmeonemails' ),
126  ],
127  ];
128  }
129 
130  public function execute( $par ) {
131  $out = $this->getOutput();
132  $request = $this->getRequest();
133  $out->addModuleStyles( 'mediawiki.special' );
134 
135  $this->mTarget = $par ?? $request->getVal( 'wpTarget', $request->getVal( 'target', '' ) );
136 
137  // This needs to be below assignment of $this->mTarget because
138  // getDescription() needs it to determine the correct page title.
139  $this->setHeaders();
140  $this->outputHeader();
141 
142  // error out if sending user cannot do this
143  $error = self::getPermissionsError(
144  $this->getUser(),
145  $this->getRequest()->getVal( 'wpEditToken' ),
146  $this->getConfig()
147  );
148 
149  switch ( $error ) {
150  case null:
151  # Wahey!
152  break;
153  case 'badaccess':
154  throw new PermissionsError( 'sendemail' );
155  case 'blockedemailuser':
156  // @phan-suppress-next-line PhanTypeMismatchArgumentNullable Block is checked and not null
157  throw new UserBlockedError( $this->getUser()->getBlock() );
158  case 'actionthrottledtext':
159  throw new ThrottledError;
160  case 'mailnologin':
161  case 'usermaildisabled':
162  throw new ErrorPageError( $error, "{$error}text" );
163  default:
164  # It's a hook error
165  [ $title, $msg, $params ] = $error;
166  throw new ErrorPageError( $title, $msg, $params );
167  }
168 
169  // A little hack: HTMLForm will check $this->mTarget only, if the form was posted, not
170  // if the user opens Special:EmailUser/Florian (e.g.). So check, if the user did that
171  // and show the "Send email to user" form directly, if so. Show the "enter username"
172  // form, otherwise.
173  // @phan-suppress-next-line PhanTypeMismatchArgumentNullable target is set
174  $this->mTargetObj = self::getTarget( $this->mTarget, $this->getUser() );
175  if ( !$this->mTargetObj instanceof User ) {
176  // @phan-suppress-next-line PhanTypeMismatchArgumentNullable target is set
177  $this->userForm( $this->mTarget );
178  } else {
179  $this->sendEmailForm();
180  }
181  }
182 
190  public static function getTarget( $target, User $sender ) {
191  return EmailUser::getTarget( $target, $sender );
192  }
193 
202  public static function validateTarget( $target, User $sender ) {
203  return EmailUser::validateTarget( $target, $sender );
204  }
205 
215  public static function getPermissionsError( $user, $editToken, Config $config = null ) {
216  return EmailUser::getPermissionsError( $user, $editToken, $config );
217  }
218 
224  protected function userForm( $name ) {
225  $htmlForm = HTMLForm::factory( 'ooui', [
226  'Target' => [
227  'type' => 'user',
228  'exists' => true,
229  'required' => true,
230  'label' => $this->msg( 'emailusername' )->text(),
231  'id' => 'emailusertarget',
232  'autofocus' => true,
233  'value' => $name,
234  ]
235  ], $this->getContext() );
236 
237  $htmlForm
238  ->setTitle( $this->getPageTitle() ) // Remove subpage
239  ->setSubmitCallback( [ $this, 'sendEmailForm' ] )
240  ->setFormIdentifier( 'userForm' )
241  ->setId( 'askusername' )
242  ->setWrapperLegendMsg( 'emailtarget' )
243  ->setSubmitTextMsg( 'emailusernamesubmit' )
244  ->show();
245  }
246 
247  public function sendEmailForm() {
248  $out = $this->getOutput();
249 
250  $ret = $this->mTargetObj;
251  if ( !$ret instanceof User ) {
252  if ( $this->mTarget != '' ) {
253  // Messages used here: notargettext, noemailtext, nowikiemailtext
254  $ret = ( $ret == 'notarget' ) ? 'emailnotarget' : ( $ret . 'text' );
255  return Status::newFatal( $ret );
256  }
257  return false;
258  }
259 
260  $htmlForm = HTMLForm::factory( 'ooui', $this->getFormFields(), $this->getContext() );
261  // By now we are supposed to be sure that $this->mTarget is a user name
262  $htmlForm
263  ->setTitle( $this->getPageTitle() ) // Remove subpage
264  ->addPreHtml( $this->msg( 'emailpagetext', $this->mTarget )->parse() )
265  ->setSubmitTextMsg( 'emailsend' )
266  ->setSubmitCallback( [ __CLASS__, 'submit' ] )
267  ->setFormIdentifier( 'sendEmailForm' )
268  ->setWrapperLegendMsg( 'email-legend' )
269  ->prepareForm();
270 
271  if ( !$this->getHookRunner()->onEmailUserForm( $htmlForm ) ) {
272  return false;
273  }
274 
275  $result = $htmlForm->show();
276 
277  if ( $result === true || ( $result instanceof Status && $result->isGood() ) ) {
278  $out->setPageTitle( $this->msg( 'emailsent' ) );
279  $out->addWikiMsg( 'emailsenttext', $this->mTarget );
280  $out->returnToMain( false, $ret->getUserPage() );
281  }
282  return true;
283  }
284 
295  public static function submit( array $data, IContextSource $context ) {
296  return EmailUser::submit( $data, $context );
297  }
298 
307  public function prefixSearchSubpages( $search, $limit, $offset ) {
308  $search = $this->userNameUtils->getCanonical( $search );
309  if ( !$search ) {
310  // No prefix suggestion for invalid user
311  return [];
312  }
313  // Autocomplete subpage as user list - public to allow caching
314  return $this->userNamePrefixSearch
315  ->search( UserNamePrefixSearch::AUDIENCE_PUBLIC, $search, $limit, $offset );
316  }
317 
318  protected function getGroupName() {
319  return 'users';
320  }
321 }
An error page which can definitely be safely rendered using the OutputPage.
static factory( $displayFormat, $descriptor, IContextSource $context, $messagePrefix='')
Construct a HTMLForm object for given display type.
Definition: HTMLForm.php:352
Command for sending emails to users.
Definition: EmailUser.php:43
Handles searching prefixes of user names.
UserNameUtils service.
Provides access to user options.
Show an error when a user tries to do something they do not have the necessary permissions for.
A special page that allows users to send e-mails to other users.
static getTarget( $target, User $sender)
Validate target User.
userForm( $name)
Form to ask for target user name.
static getPermissionsError( $user, $editToken, Config $config=null)
Check whether a user is allowed to send email.
static validateTarget( $target, User $sender)
Validate target User.
static submit(array $data, IContextSource $context)
Really send a mail.
prefixSearchSubpages( $search, $limit, $offset)
Return an array of subpages beginning with $search that this special page will accept.
User string $mTargetObj
doesWrites()
Indicates whether this special page may perform database writes.
__construct(UserNameUtils $userNameUtils, UserNamePrefixSearch $userNamePrefixSearch, UserOptionsLookup $userOptionsLookup)
getDescription()
Returns the name that goes in the <h1> in the special page itself, and also the name that will be l...
execute( $par)
Default execute method Checks user permissions.
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
outputHeader( $summaryMessageKey='')
Outputs a summary message on top of special pages Per default the message key is the canonical name o...
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
getOutput()
Get the OutputPage being used for this instance.
getUser()
Shortcut to get the User executing this instance.
getContext()
Gets the context this SpecialPage is executed in.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getConfig()
Shortcut to get main config object.
getRequest()
Get the WebRequest being used for this instance.
getPageTitle( $subpage=false)
Get a self-referential title object.
static newFatal( $message,... $parameters)
Factory function for fatal errors.
Definition: StatusValue.php:73
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:46
Show an error when the user hits a rate limit.
Shortcut to construct a special page which is unlisted by default.
Show an error when the user tries to do something whilst blocked.
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:71
Interface for configuration instances.
Definition: Config.php:30
Interface for objects which can provide a MediaWiki context on request.