2 namespace TYPO3\CMS\Setup\Controller;
29 use TYPO3\CMS\Core\Resource\Exception\FileDoesNotExistException;
170 parent::__construct();
191 public function storeIncomingData()
195 $columns =
$GLOBALS[
'TYPO3_USER_SETTINGS'][
'columns'];
197 $beUserId = $beUser->user[
'uid'];
200 if (is_array($d) && $this->formProtection->validateToken((
string)
GeneralUtility::_POST(
'formToken'),
'BE user setup',
'edit')) {
202 $save_before = md5(serialize($beUser->uc));
205 if (isset($d[
'lang']) && $d[
'lang'] != $beUser->uc[
'lang']) {
206 $this->languageUpdate =
true;
209 if (isset($d[
'titleLen']) && $d[
'titleLen'] !== $beUser->uc[
'titleLen']) {
210 $this->pagetreeNeedsRefresh =
true;
212 if ($d[
'setValuesToDefault']) {
215 $this->settingsAreResetToDefault =
true;
218 foreach ($columns as $field => $config) {
219 if (!in_array($field, $fieldList)) {
222 if ($config[
'table']) {
223 if ($config[
'table'] ===
'be_users' && !in_array($field, array(
'password',
'password2',
'passwordCurrent',
'email',
'realName',
'admin',
'avatar'))) {
224 if (!isset($config[
'access']) || $this->
checkAccess($config) && $beUser->user[$field] !== $d[
'be_users'][$field]) {
225 if ($config[
'type'] ===
'check') {
226 $fieldValue = isset($d[
'be_users'][$field]) ? 1 : 0;
228 $fieldValue = $d[
'be_users'][$field];
230 $storeRec[
'be_users'][$beUserId][$field] = $fieldValue;
231 $beUser->user[$field] = $fieldValue;
235 if ($config[
'type'] ===
'check') {
236 $beUser->uc[$field] = isset($d[$field]) ? 1 : 0;
238 $beUser->uc[$field] = htmlspecialchars($d[$field]);
243 $be_user_data = $d[
'be_users'];
245 if (is_array(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'ext/setup/mod/index.php'][
'modifyUserDataBeforeSave'])) {
246 foreach (
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'ext/setup/mod/index.php'][
'modifyUserDataBeforeSave'] as $function) {
247 $params = array(
'be_user_data' => &$be_user_data);
251 $this->passwordIsSubmitted = (string)$be_user_data[
'password'] !==
'';
252 $passwordIsConfirmed = $this->passwordIsSubmitted && $be_user_data[
'password'] === $be_user_data[
'password2'];
254 if ($be_user_data[
'realName'] !== $beUser->user[
'realName']) {
255 $beUser->user[
'realName'] = ($storeRec[
'be_users'][$beUserId][
'realName'] = substr($be_user_data[
'realName'], 0, 80));
258 if ($be_user_data[
'email'] !== $beUser->user[
'email']) {
259 $beUser->user[
'email'] = ($storeRec[
'be_users'][$beUserId][
'email'] = substr($be_user_data[
'email'], 0, 80));
262 if ($passwordIsConfirmed) {
263 $currentPasswordHashed =
$GLOBALS[
'BE_USER']->user[
'password'];
264 $saltFactory = \TYPO3\CMS\Saltedpasswords\Salt\SaltFactory::getSaltingInstance($currentPasswordHashed);
265 if ($saltFactory->checkPassword($be_user_data[
'passwordCurrent'], $currentPasswordHashed)) {
266 $this->passwordIsUpdated = self::PASSWORD_UPDATED;
267 $storeRec[
'be_users'][$beUserId][
'password'] = $be_user_data[
'password'];
269 $this->passwordIsUpdated = self::PASSWORD_OLD_WRONG;
272 $this->passwordIsUpdated = self::PASSWORD_NOT_THE_SAME;
277 $this->saveData =
true;
280 $beUser->overrideUC();
281 $save_after = md5(serialize($beUser->uc));
283 if ($save_before != $save_after) {
284 $beUser->writeUC($beUser->uc);
285 $beUser->writelog(254, 1, 0, 1,
'Personal settings changed', array());
286 $this->setupIsUpdated =
true;
289 if (!empty($storeRec) && $this->saveData) {
293 $dataHandler->stripslashes_values =
false;
296 $beUser->user[
'admin'] = 1;
297 $dataHandler->start($storeRec, array(), $beUser);
299 $dataHandler->bypassWorkspaceRestrictions =
true;
300 $dataHandler->process_datamap();
302 if ($this->passwordIsUpdated === self::PASSWORD_NOT_UPDATED || count($storeRec[
'be_users'][$beUserId]) > 1) {
303 $this->setupIsUpdated =
true;
323 $this->
getLanguageService()->includeLLFile(
'EXT:setup/Resources/Private/Language/locallang.xlf');
328 $this->isAdmin = $scriptUser->isAdmin();
330 $this->overrideConf = $this->
getBackendUser()->getTSConfigProp(
'setup.override');
332 $this->tsFieldConf = $this->
getBackendUser()->getTSConfigProp(
'setup.fields');
334 if (isset($this->tsFieldConf[
'password.']) && $this->tsFieldConf[
'password.'][
'disabled']) {
335 $this->tsFieldConf[
'password2.'][
'disabled'] = 1;
336 $this->tsFieldConf[
'passwordCurrent.'][
'disabled'] = 1;
350 if (is_array(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'ext/setup/mod/index.php'][
'setupScriptHook'])) {
351 foreach (
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'ext/setup/mod/index.php'][
'setupScriptHook'] as $function) {
366 $this->content .=
'<form action="' . BackendUtility::getModuleUrl(
'user_setup') .
'" method="post" id="SetupModuleController" name="usersetup" enctype="multipart/form-data">';
367 if ($this->languageUpdate) {
368 $this->moduleTemplate->addJavaScriptCode(
'languageUpdate',
'
369 if (top.refreshMenu) {
372 top.TYPO3ModuleMenu.refreshMenu();
376 if ($this->pagetreeNeedsRefresh) {
380 $this->moduleTemplate->loadJavascriptLib(
'sysext/backend/Resources/Public/JavaScript/md5.js');
382 $this->content .=
'<div id="user-setup-wrapper">';
385 $this->loadModules->observeWorkspaces =
true;
386 $this->loadModules->load(
$GLOBALS[
'TBE_MODULES']);
387 $this->content .= $this->doc->header($this->
getLanguageService()->getLL(
'UserSettings'));
389 if ($this->setupIsUpdated && !$this->settingsAreResetToDefault) {
391 $this->content .= $flashMessage->render();
395 if ($this->settingsAreResetToDefault) {
397 $this->content .= $flashMessage->render();
401 if ($this->setupIsUpdated || $this->settingsAreResetToDefault) {
403 $this->content .= $flashMessage->render();
407 if ($this->passwordIsSubmitted) {
408 $flashMessage = null;
409 switch ($this->passwordIsUpdated) {
410 case self::PASSWORD_OLD_WRONG:
413 case self::PASSWORD_NOT_THE_SAME:
416 case self::PASSWORD_UPDATED:
421 $this->content .= $flashMessage->render();
430 $this->content .= $this->moduleTemplate->getDynamicTabMenu($menuItems,
'user-setup', 1,
false,
false);
431 $formToken = $this->formProtection->generateToken(
'BE user setup',
'edit');
432 $this->content .=
'<div>';
433 $this->content .=
'<input type="hidden" name="simUser" value="' . $this->simUser .
'" />
434 <input type="hidden" name="formToken" value="' . $formToken .
'" />
435 <input type="hidden" value="1" name="data[save]" />
436 <input type="hidden" name="data[setValuesToDefault]" value="0" id="setValuesToDefault" />';
437 $this->content .=
'</div>';
439 $this->content .=
'</div>';
444 $this->moduleTemplate->setContent($this->content);
445 $this->content .=
'</form>';
461 $this->storeIncomingData();
465 $response->
getBody()->write($this->moduleTemplate->renderContent());
486 $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
487 $cshButton = $buttonBar->makeHelpButton()
488 ->setModuleName(
'_MOD_user_setup')
490 $buttonBar->addButton($cshButton);
492 $saveButton = $buttonBar->makeInputButton()
493 ->setName(
'data[save]')
494 ->setTitle($this->
getLanguageService()->sL(
'LLL:EXT:lang/locallang_core.xlf:rm.saveDoc',
true))
496 ->setForm(
'SetupModuleController')
497 ->setShowLabelText(
true)
498 ->setIcon($this->moduleTemplate->getIconFactory()->getIcon(
'actions-document-save',
Icon::SIZE_SMALL));
500 $buttonBar->addButton($saveButton);
501 $shortcutButton = $buttonBar->makeShortcutButton()
502 ->setModuleName($this->moduleName);
503 $buttonBar->addButton($shortcutButton);
526 foreach ($fieldArray as $fieldName) {
528 if (substr($fieldName, 0, 8) ===
'--div--;') {
529 if ($firstTabLabel ===
'') {
531 $tabLabel = $this->
getLabel(substr($fieldName, 8),
'',
false);
532 $firstTabLabel = $tabLabel;
535 'label' => $tabLabel,
536 'content' => count($code) ? implode(LF, $code) :
''
538 $tabLabel = $this->
getLabel(substr($fieldName, 8),
'',
false);
543 $config =
$GLOBALS[
'TYPO3_USER_SETTINGS'][
'columns'][$fieldName];
546 if (isset($this->tsFieldConf[$fieldName .
'.'][
'disabled']) && $this->tsFieldConf[$fieldName .
'.'][
'disabled'] == 1) {
549 if (isset($config[
'access']) && !$this->
checkAccess($config)) {
552 $label = $this->
getLabel($config[
'label'], $fieldName);
553 $label = $this->
getCSH($config[
'csh'] ?: $fieldName, $label);
554 $type = $config[
'type'];
555 $class = $config[
'class'];
557 if ($type !==
'check') {
558 $class .=
' form-control';
561 $style = $config[
'style'];
563 $more .=
' class="' . $class .
'"';
566 $more .=
' style="' . $style .
'"';
568 if (isset($this->overrideConf[$fieldName])) {
569 $more .=
' disabled="disabled"';
572 if (!$value && isset($config[
'default'])) {
573 $value = $config[
'default'];
576 if ($config[
'table'] ===
'be_users') {
577 $dataAdd =
'[be_users]';
584 $noAutocomplete =
'';
585 if ($type ===
'password') {
587 $noAutocomplete =
'autocomplete="off" ';
588 $more .=
' data-rsa-encryption=""';
590 $html =
'<input id="field_' . $fieldName .
'"
592 name="data' . $dataAdd .
'[' . $fieldName .
']" ' .
594 'value="' . htmlspecialchars($value) .
'" ' .
599 $html = $label .
'<div class="checkbox"><label><input id="field_' . $fieldName .
'"
601 name="data' . $dataAdd .
'[' . $fieldName .
']"' .
602 ($value ?
' checked="checked"' :
'') .
608 if ($config[
'itemsProcFunc']) {
611 $html =
'<select id="field_' . $fieldName .
'"
612 name="data' . $dataAdd .
'[' . $fieldName .
']"' .
614 foreach ($config[
'items'] as $key => $optionLabel) {
615 $html .=
'<option value="' . $key .
'"' . ($value == $key ?
' selected="selected"' :
'') .
'>' . $this->
getLabel($optionLabel,
'',
false) .
'</option>' . LF;
617 $html .=
'</select>';
624 if ($config[
'onClick']) {
625 $onClick = $config[
'onClick'];
626 if ($config[
'onClickLabels']) {
627 foreach ($config[
'onClickLabels'] as $key => $labelclick) {
628 $config[
'onClickLabels'][$key] = $this->
getLabel($labelclick,
'',
false);
630 $onClick = vsprintf($onClick, $config[
'onClickLabels']);
632 $html =
'<br><input class="btn btn-default" type="button"
633 value="' . $this->
getLabel($config[
'buttonlabel'],
'',
false) .
'"
634 onclick="' . $onClick .
'" />';
642 if ($avatarFileUid) {
644 $avatarImage = $defaultAvatarProvider->getImage($this->
getBackendUser()->user, 32);
646 $icon =
'<span class="avatar"><span class="avatar-image">' .
647 '<img src="' . htmlspecialchars($avatarImage->getUrl(
true)) .
'"' .
648 ' width="' . (
int)$avatarImage->getWidth() .
'" ' .
649 'height="' . (int)$avatarImage->getHeight() .
'" />' .
651 $html .=
'<span class="pull-left" style="padding-right: 10px" id="image_' . htmlspecialchars($fieldName) .
'">' . $icon .
' </span>';
654 $html .=
'<input id="field_' . htmlspecialchars($fieldName) .
'" type="hidden" ' .
655 'name="data' . $dataAdd .
'[' . htmlspecialchars($fieldName) .
']"' . $more .
656 ' value="' . $avatarFileUid .
'" />';
658 $html .=
'<div class="btn-group">';
659 if ($avatarFileUid) {
660 $html .=
'<a id="clear_button_' . htmlspecialchars($fieldName) .
'" onclick="clearExistingImage(); return false;" class="btn btn-default"><span class="t3-icon fa t3-icon fa fa-remove"> </span></a>';
662 $html .=
'<a id="add_button_' . htmlspecialchars($fieldName) .
'" class="btn btn-default btn-add-avatar" onclick="openFileBrowser();return false;"><span class="t3-icon t3-icon-actions t3-icon-actions-insert t3-icon-insert-record"> </span></a>' .
671 $code[] =
'<div class="form-section"><div class="form-group">' .
678 'label' => $tabLabel,
679 'content' => count($code) ? implode(LF, $code) :
''
697 return is_object($this->OLD_BE_USER) ? $this->OLD_BE_USER : $this->
getBackendUser();
707 public function renderLanguageSelect($params)
709 $languageOptions = array();
712 $languageOptions[$langDefault] =
'<option value=""' . ($this->
getBackendUser()->uc[
'lang'] ===
'' ?
' selected="selected"' :
'') .
'>' . $langDefault .
'</option>';
716 $languages =
$locales->getLanguages();
717 foreach ($languages as $locale => $name) {
718 if ($locale !==
'default') {
719 $defaultName = isset(
$GLOBALS[
'LOCAL_LANG'][
'default'][
'lang_' . $locale]) ?
$GLOBALS[
'LOCAL_LANG'][
'default'][
'lang_' . $locale][0][
'source'] : $name;
721 if ($localizedName ===
'') {
722 $localizedName = htmlspecialchars($name);
724 $localLabel =
' - [' . htmlspecialchars($defaultName) .
']';
725 $available = is_dir(PATH_typo3conf .
'l10n/' . $locale);
727 $languageOptions[$defaultName] =
'<option value="' . $locale .
'"' . ($this->
getBackendUser()->uc[
'lang'] === $locale ?
' selected="selected"' :
'') .
'>' . $localizedName . $localLabel .
'</option>';
731 ksort($languageOptions);
733 <select id="field_lang" name="data[lang]" class="form-control">' . implode(
'', $languageOptions) .
'
736 $languageUnavailableWarning =
'The selected language "' . $this->
getLanguageService()->getLL((
'lang_' . $this->
getBackendUser()->uc[
'lang']),
true) .
'" is not available before the language files are installed.<br />' . ($this->
getBackendUser()->isAdmin() ?
'You can use the Language module to easily download new language files.' :
'Please ask your system administrator to do this.');
738 $languageCode = $languageUnavailableMessage->render() . $languageCode;
740 return $languageCode;
753 $startModuleSelect =
'<option value="">' . $this->
getLanguageService()->getLL(
'startModule.firstInMenu',
true) .
'</option>';
754 foreach ($pObj->loadModules->modules as $mainMod => $modData) {
755 if (!empty($modData[
'sub']) && is_array($modData[
'sub'])) {
757 foreach ($modData[
'sub'] as $subData) {
758 $modName = $subData[
'name'];
759 $modules .=
'<option value="' . htmlspecialchars($modName) .
'"';
760 $modules .= $this->
getBackendUser()->uc[
'startModule'] === $modName ?
' selected="selected"' :
'';
761 $modules .=
'>' . $this->
getLanguageService()->moduleLabels[
'tabs'][$modName .
'_tab'] .
'</option>';
764 $startModuleSelect .=
'<optgroup label="' . htmlspecialchars($groupLabel) .
'">' . $modules .
'</optgroup>';
767 return '<select id="field_startModule" name="data[startModule]" class="form-control">' . $startModuleSelect .
'</select>';
780 $this->simulateSelector =
'';
781 unset($this->OLD_BE_USER);
786 $where =
'AND username NOT LIKE ' . $db->fullQuoteStr($db->escapeStrForLike(
'_cli_',
'be_users') .
'%',
'be_users');
790 foreach ($users as $rr) {
791 $label = htmlspecialchars(($rr[
'username'] . ($rr[
'realName'] ?
' (' . $rr[
'realName'] .
')' :
'')));
792 $opt[] =
'<option value="' . $rr[
'uid'] .
'"' . ($this->simUser == $rr[
'uid'] ?
' selected="selected"' :
'') .
'>' . $label .
'</option>';
795 $this->simulateSelector =
'<select id="field_simulate" name="simulateUser" onchange="window.location.href=' .
GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl(
'user_setup') .
'&simUser=') .
'+this.options[this.selectedIndex].value;"><option></option>' . implode(
'', $opt) .
'</select>';
799 if ($this->simUser > 0) {
806 $BE_USER->setBeUserByUid($this->simUser);
807 $BE_USER->fetchGroupData();
808 $BE_USER->backendSetUC();
821 if ($this->simulateSelector ===
'') {
826 '<label for="field_simulate" style="margin-right: 20px;">' .
827 $this->
getLanguageService()->sL(
'LLL:EXT:setup/Resources/Private/Language/locallang.xlf:simulate') .
829 $this->simulateSelector .
841 $access = $config[
'access'];
843 if (isset(
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'setup'][
'accessLevelCheck'][$access])) {
844 if (class_exists($access)) {
846 if (method_exists($accessObject,
'accessLevelCheck')) {
848 return $accessObject->accessLevelCheck($config);
851 }
elseif ($access ==
'admin') {
867 protected function getLabel($str, $key =
'', $addLabelTag =
true, $altLabelTagId =
'')
869 if (substr($str, 0, 4) ===
'LLL:') {
872 $out = htmlspecialchars($str);
874 if (isset($this->overrideConf[$key ?: $str])) {
875 $out =
'<span style="color:#999999">' . $out .
'</span>';
878 $out =
'<label for="' . ($altLabelTagId ?:
'field_' . $key) .
'">' . $out .
'</label>';
892 $context =
'_MOD_user_setup';
894 $strParts = explode(
':', $str);
895 if (count($strParts) > 1) {
897 $context = $strParts[0];
898 $field = $strParts[1];
900 $field =
'option_' . $str;
902 return BackendUtility::wrapInHelp($context, $field, $label);
925 'sys_file_reference',
926 'tablenames = \'be_users\' AND fieldname = \'avatar\' AND ' .
927 'table_local = \'sys_file\' AND uid_foreign = ' . (
int)$beUserId .
930 return $file ? $file[
'uid_local'] : 0;
950 'sys_file_reference',
951 'tablenames = \'be_users\' AND fieldname = \'avatar\' AND ' .
952 'table_local = \'sys_file\' AND uid_foreign = ' . (
int)$beUserId
966 if ($file && $this->simUser === 0 && !$file->getStorage()->checkFileActionPermission(
'read', $file)) {
974 $storeRec[
'sys_file_reference'][
'NEW1234'] = array(
975 'uid_local' => $fileUid,
976 'uid_foreign' => $beUserId,
977 'tablenames' =>
'be_users',
978 'fieldname' =>
'avatar',
980 'table_local' =>
'sys_file',
982 $storeRec[
'be_users'][(int)$beUserId][
'avatar'] =
'NEW1234';
994 $this->moduleTemplate->addJavaScriptCode(
'avatar-button',
'
997 function openFileBrowser() {
998 var url = ' .
GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl(
'wizard_element_browser', [
'mode' =>
'file',
'bparams' =>
'||||dummy|setFileUid'])) .
';
999 browserWin = window.open(url,"Typo3WinBrowser","height=650,width=800,status=0,menubar=0,resizable=1,scrollbars=1");
1003 function clearExistingImage() {
1004 TYPO3.jQuery(\'#image_' . htmlspecialchars($fieldName) .
'\').hide();
1005 TYPO3.jQuery(\
'#clear_button_' . htmlspecialchars($fieldName) .
'\').hide();
1006 TYPO3.jQuery(\
'#field_' . htmlspecialchars($fieldName) .
'\').val(\
'\');
1009 function setFileUid(field, value, fileUid) {
1010 clearExistingImage();
1011 TYPO3.jQuery(\
'#field_' . htmlspecialchars($fieldName) .
'\').val(fileUid);
1012 TYPO3.jQuery(\
'#add_button_' . htmlspecialchars($fieldName) .
'\').removeClass(\
'btn-default\').addClass(\'btn-info\');