Fixed time zone calculation issue
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / acp / form / UserAddForm.class.php
1 <?php
2 namespace wcf\acp\form;
3 use wcf\data\user\group\UserGroup;
4 use wcf\data\user\UserAction;
5 use wcf\data\user\UserEditor;
6 use wcf\data\user\UserProfileAction;
7 use wcf\form\AbstractForm;
8 use wcf\system\database\util\PreparedStatementConditionBuilder;
9 use wcf\system\exception\UserInputException;
10 use wcf\system\language\LanguageFactory;
11 use wcf\system\WCF;
12 use wcf\util\ArrayUtil;
13 use wcf\util\StringUtil;
14 use wcf\util\UserUtil;
15
16 /**
17 * Shows the user add form.
18 *
19 * @author Marcel Werk
20 * @copyright 2001-2014 WoltLab GmbH
21 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
22 * @package com.woltlab.wcf
23 * @subpackage acp.form
24 * @category Community Framework
25 */
26 class UserAddForm extends UserOptionListForm {
27 /**
28 * @see \wcf\page\AbstractPage::$activeMenuItem
29 */
30 public $activeMenuItem = 'wcf.acp.menu.link.user.add';
31
32 /**
33 * @see \wcf\page\AbstractPage::$neededPermissions
34 */
35 public $neededPermissions = array('admin.user.canAddUser');
36
37 /**
38 * username
39 * @var string
40 */
41 public $username = '';
42
43 /**
44 * email address
45 * @var string
46 */
47 public $email = '';
48
49 /**
50 * confirmed email address
51 * @var string
52 */
53 public $confirmEmail = '';
54
55 /**
56 * user password
57 * @var string
58 */
59 public $password = '';
60
61 /**
62 * confirmed user password
63 * @var string
64 */
65 public $confirmPassword = '';
66
67 /**
68 * user group ids
69 * @var array<integer>
70 */
71 public $groupIDs = array();
72
73 /**
74 * language id
75 * @var integer
76 */
77 public $languageID = 0;
78
79 /**
80 * visible languages
81 * @var array<integer>
82 */
83 public $visibleLanguages = array();
84
85 /**
86 * title of the user
87 * @var string
88 */
89 protected $userTitle = '';
90
91 /**
92 * signature text
93 * @var string
94 */
95 public $signature = '';
96
97 /**
98 * enables smilies
99 * @var boolean
100 */
101 public $signatureEnableSmilies = 1;
102
103 /**
104 * enables bbcodes
105 * @var boolean
106 */
107 public $signatureEnableBBCodes = 1;
108
109 /**
110 * enables html
111 * @var boolean
112 */
113 public $signatureEnableHtml = 0;
114
115 /**
116 * true to disable this signature
117 * @var boolean
118 */
119 public $disableSignature = 0;
120
121 /**
122 * reason
123 * @var string
124 */
125 public $disableSignatureReason = '';
126
127 /**
128 * @see \wcf\form\IForm::readFormParameters()
129 */
130 public function readFormParameters() {
131 parent::readFormParameters();
132
133 if (isset($_POST['username'])) $this->username = StringUtil::trim($_POST['username']);
134 if (isset($_POST['email'])) $this->email = StringUtil::trim($_POST['email']);
135 if (isset($_POST['confirmEmail'])) $this->confirmEmail = StringUtil::trim($_POST['confirmEmail']);
136 if (isset($_POST['password'])) $this->password = $_POST['password'];
137 if (isset($_POST['confirmPassword'])) $this->confirmPassword = $_POST['confirmPassword'];
138 if (isset($_POST['groupIDs']) && is_array($_POST['groupIDs'])) $this->groupIDs = ArrayUtil::toIntegerArray($_POST['groupIDs']);
139 if (isset($_POST['visibleLanguages']) && is_array($_POST['visibleLanguages'])) $this->visibleLanguages = ArrayUtil::toIntegerArray($_POST['visibleLanguages']);
140 if (isset($_POST['languageID'])) $this->languageID = intval($_POST['languageID']);
141 if (isset($_POST['userTitle'])) $this->userTitle = $_POST['userTitle'];
142
143 if (isset($_POST['signature'])) $this->signature = StringUtil::trim($_POST['signature']);
144 if (isset($_POST['disableSignatureReason'])) $this->disableSignatureReason = StringUtil::trim($_POST['disableSignatureReason']);
145
146 $this->signatureEnableBBCodes = $this->signatureEnableSmilies = 0;
147 if (!empty($_POST['signatureEnableBBCodes'])) $this->signatureEnableBBCodes = 1;
148 if (!empty($_POST['signatureEnableSmilies'])) $this->signatureEnableSmilies = 1;
149 if (!empty($_POST['signatureEnableHtml'])) $this->signatureEnableHtml = 1;
150 if (!empty($_POST['disableSignature'])) $this->disableSignature = 1;
151 }
152
153 /**
154 * @see \wcf\form\IForm::validate()
155 */
156 public function validate() {
157 // validate static user options
158 try {
159 $this->validateUsername($this->username);
160 }
161 catch (UserInputException $e) {
162 $this->errorType[$e->getField()] = $e->getType();
163 }
164
165 try {
166 $this->validateEmail($this->email, $this->confirmEmail);
167 }
168 catch (UserInputException $e) {
169 $this->errorType[$e->getField()] = $e->getType();
170 }
171
172 try {
173 $this->validatePassword($this->password, $this->confirmPassword);
174 }
175 catch (UserInputException $e) {
176 $this->errorType[$e->getField()] = $e->getType();
177 }
178
179 // validate user groups
180 if (!empty($this->groupIDs)) {
181 $conditions = new PreparedStatementConditionBuilder();
182 $conditions->add("groupID IN (?)", array($this->groupIDs));
183 $conditions->add("groupType NOT IN (?)", array(array(UserGroup::GUESTS, UserGroup::EVERYONE, UserGroup::USERS)));
184
185 $sql = "SELECT groupID
186 FROM wcf".WCF_N."_user_group
187 ".$conditions;
188 $statement = WCF::getDB()->prepareStatement($sql);
189 $statement->execute($conditions->getParameters());
190 $this->groupIDs = array();
191 while ($row = $statement->fetchArray()) {
192 if (UserGroup::isAccessibleGroup(array($row['groupID']))) {
193 $this->groupIDs[] = $row['groupID'];
194 }
195 }
196 }
197
198 // validate user language
199 $language = LanguageFactory::getInstance()->getLanguage($this->languageID);
200 if ($language === null || !$language->languageID) {
201 // use default language
202 $this->languageID = LanguageFactory::getInstance()->getDefaultLanguageID();
203 }
204
205 // validate visible languages
206 foreach ($this->visibleLanguages as $key => $visibleLanguage) {
207 $language = LanguageFactory::getInstance()->getLanguage($visibleLanguage);
208 if (!$language->languageID || !$language->hasContent) {
209 unset($this->visibleLanguages[$key]);
210 }
211 }
212 if (empty($this->visibleLanguages) && ($language = LanguageFactory::getInstance()->getLanguage($this->languageID)) && $language->hasContent) {
213 $this->visibleLanguages[] = $this->languageID;
214 }
215
216 // validate user title
217 try {
218 if (mb_strlen($this->userTitle) > USER_TITLE_MAX_LENGTH) {
219 throw new UserInputException('userTitle', 'tooLong');
220 }
221 if (!StringUtil::executeWordFilter($this->userTitle, USER_FORBIDDEN_TITLES)) {
222 throw new UserInputException('userTitle', 'forbidden');
223 }
224 }
225 catch (UserInputException $e) {
226 $this->errorType[$e->getField()] = $e->getType();
227 }
228
229 // validate dynamic options
230 parent::validate();
231 }
232
233 /**
234 * @see \wcf\form\IForm::save()
235 */
236 public function save() {
237 AbstractForm::save();
238
239 // create
240 $saveOptions = $this->optionHandler->save();
241 $this->additionalFields['languageID'] = $this->languageID;
242 $data = array(
243 'data' => array_merge($this->additionalFields, array(
244 'username' => $this->username,
245 'email' => $this->email,
246 'password' => $this->password,
247 'userTitle' => $this->userTitle,
248 'signature' => $this->signature,
249 'signatureEnableBBCodes' => $this->signatureEnableBBCodes,
250 'signatureEnableSmilies' => $this->signatureEnableSmilies,
251 'signatureEnableHtml' => $this->signatureEnableHtml,
252 'disableSignature' => $this->disableSignature,
253 'disableSignatureReason' => $this->disableSignatureReason
254 )),
255 'groups' => $this->groupIDs,
256 'languages' => $this->visibleLanguages,
257 'options' => $saveOptions
258 );
259 $this->objectAction = new UserAction(array(), 'create', $data);
260 $this->objectAction->executeAction();
261 $this->saved();
262
263 // show empty add form
264 WCF::getTPL()->assign(array(
265 'success' => true
266 ));
267
268 // reset values
269 $this->username = $this->email = $this->confirmEmail = $this->password = $this->confirmPassword = '';
270 $this->groupIDs = array();
271 $this->languageID = $this->getDefaultFormLanguageID();
272 $this->optionHandler->resetOptionValues();
273 }
274
275 /**
276 * Throws a UserInputException if the username is not unique or not valid.
277 *
278 * @param string $username
279 */
280 protected function validateUsername($username) {
281 if (empty($username)) {
282 throw new UserInputException('username');
283 }
284
285 // check for forbidden chars (e.g. the ",")
286 if (!UserUtil::isValidUsername($username)) {
287 throw new UserInputException('username', 'notValid');
288 }
289
290 // Check if username exists already.
291 if (!UserUtil::isAvailableUsername($username)) {
292 throw new UserInputException('username', 'notUnique');
293 }
294 }
295
296 /**
297 * Throws a UserInputException if the email is not unique or not valid.
298 *
299 * @param string $email
300 * @param string $confirmEmail
301 */
302 protected function validateEmail($email, $confirmEmail) {
303 if (empty($email)) {
304 throw new UserInputException('email');
305 }
306
307 // check for valid email (one @ etc.)
308 if (!UserUtil::isValidEmail($email)) {
309 throw new UserInputException('email', 'notValid');
310 }
311
312 // Check if email exists already.
313 if (!UserUtil::isAvailableEmail($email)) {
314 throw new UserInputException('email', 'notUnique');
315 }
316
317 // check confirm input
318 if (mb_strtolower($email) != mb_strtolower($confirmEmail)) {
319 throw new UserInputException('confirmEmail', 'notEqual');
320 }
321 }
322
323 /**
324 * Throws a UserInputException if the password is not valid.
325 *
326 * @param string $password
327 * @param string $confirmPassword
328 */
329 protected function validatePassword($password, $confirmPassword) {
330 if (empty($password)) {
331 throw new UserInputException('password');
332 }
333
334 // check confirm input
335 if ($password != $confirmPassword) {
336 throw new UserInputException('confirmPassword', 'notEqual');
337 }
338 }
339
340 /**
341 * @see \wcf\page\IPage::readData()
342 */
343 public function readData() {
344 parent::readData();
345
346 $this->readOptionTree();
347 }
348
349 /**
350 * Reads option tree on page init.
351 */
352 protected function readOptionTree() {
353 $this->optionTree = $this->optionHandler->getOptionTree();
354 }
355
356 /**
357 * @see \wcf\page\IPage::assignVariables()
358 */
359 public function assignVariables() {
360 parent::assignVariables();
361
362 WCF::getTPL()->assign(array(
363 'username' => $this->username,
364 'email' => $this->email,
365 'confirmEmail' => $this->confirmEmail,
366 'password' => $this->password,
367 'confirmPassword' => $this->confirmPassword,
368 'groupIDs' => $this->groupIDs,
369 'optionTree' => $this->optionTree,
370 'availableGroups' => $this->getAvailableGroups(),
371 'availableLanguages' => LanguageFactory::getInstance()->getLanguages(),
372 'languageID' => $this->languageID,
373 'visibleLanguages' => $this->visibleLanguages,
374 'availableContentLanguages' => LanguageFactory::getInstance()->getContentLanguages(),
375 'action' => 'add',
376 'userTitle' => $this->userTitle,
377 'signature' => $this->signature,
378 'signatureEnableBBCodes' => $this->signatureEnableBBCodes,
379 'signatureEnableSmilies' => $this->signatureEnableSmilies,
380 'signatureEnableHtml' => $this->signatureEnableHtml,
381 'disableSignature' => $this->disableSignature,
382 'disableSignatureReason' => $this->disableSignatureReason
383 ));
384 }
385
386 /**
387 * @see \wcf\page\IPage::show()
388 */
389 public function show() {
390 // get the default language id
391 $this->languageID = $this->getDefaultFormLanguageID();
392
393 // show form
394 parent::show();
395 }
396 }