TYPO3CMS  8
 All Classes Namespaces Files Functions Variables Pages
SetupModuleController.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Setup\Controller;
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
17 use Psr\Http\Message\ResponseInterface;
18 use Psr\Http\Message\ServerRequestInterface;
34 
39 {
44 
48  const PASSWORD_UPDATED = 1;
49 
54 
59  const PASSWORD_OLD_WRONG = 3;
60 
64  public $MOD_MENU = [];
65 
69  public $MOD_SETTINGS = [];
70 
74  public $content;
75 
79  public $overrideConf;
80 
86  public $OLD_BE_USER;
87 
92 
96  protected $pagetreeNeedsRefresh = false;
97 
101  protected $isAdmin;
102 
106  protected $tsFieldConf;
107 
111  protected $saveData = false;
112 
116  protected $passwordIsUpdated = self::PASSWORD_NOT_UPDATED;
117 
121  protected $passwordIsSubmitted = false;
122 
126  protected $setupIsUpdated = false;
127 
131  protected $settingsAreResetToDefault = false;
132 
138  protected $formProtection;
139 
143  protected $simulateSelector = '';
144 
148  protected $simUser;
149 
155  protected $moduleName = 'user_setup';
156 
160  protected $loadModules;
161 
165  public function __construct()
166  {
167  parent::__construct();
168  $this->formProtection = FormProtectionFactory::get();
169  $this->moduleTemplate->getPageRenderer()->loadRequireJsModule('TYPO3/CMS/Backend/Modal');
170  }
171 
177  public function getFormProtection()
178  {
179  return $this->formProtection;
180  }
181 
187  public function storeIncomingData()
188  {
189  // First check if something is submitted in the data-array from POST vars
190  $d = GeneralUtility::_POST('data');
191  $columns = $GLOBALS['TYPO3_USER_SETTINGS']['columns'];
192  $beUser = $this->getBackendUser();
193  $beUserId = $beUser->user['uid'];
194  $storeRec = [];
195  $fieldList = $this->getFieldsFromShowItem();
196  if (is_array($d) && $this->formProtection->validateToken((string)GeneralUtility::_POST('formToken'), 'BE user setup', 'edit')) {
197  // UC hashed before applying changes
198  $save_before = md5(serialize($beUser->uc));
199  // PUT SETTINGS into the ->uc array:
200  // Reload left frame when switching BE language
201  if (isset($d['lang']) && $d['lang'] != $beUser->uc['lang']) {
202  $this->languageUpdate = true;
203  }
204  // Reload pagetree if the title length is changed
205  if (isset($d['titleLen']) && $d['titleLen'] !== $beUser->uc['titleLen']) {
206  $this->pagetreeNeedsRefresh = true;
207  }
208  if ($d['setValuesToDefault']) {
209  // If every value should be default
210  $beUser->resetUC();
211  $this->settingsAreResetToDefault = true;
212  } elseif ($d['save']) {
213  // Save all submitted values if they are no array (arrays are with table=be_users) and exists in $GLOBALS['TYPO3_USER_SETTINGS'][columns]
214  foreach ($columns as $field => $config) {
215  if (!in_array($field, $fieldList)) {
216  continue;
217  }
218  if ($config['table']) {
219  if ($config['table'] === 'be_users' && !in_array($field, ['password', 'password2', 'passwordCurrent', 'email', 'realName', 'admin', 'avatar'])) {
220  if (!isset($config['access']) || $this->checkAccess($config) && $beUser->user[$field] !== $d['be_users'][$field]) {
221  if ($config['type'] === 'check') {
222  $fieldValue = isset($d['be_users'][$field]) ? 1 : 0;
223  } else {
224  $fieldValue = $d['be_users'][$field];
225  }
226  $storeRec['be_users'][$beUserId][$field] = $fieldValue;
227  $beUser->user[$field] = $fieldValue;
228  }
229  }
230  }
231  if ($config['type'] === 'check') {
232  $beUser->uc[$field] = isset($d[$field]) ? 1 : 0;
233  } else {
234  $beUser->uc[$field] = htmlspecialchars($d[$field]);
235  }
236  }
237  // Personal data for the users be_user-record (email, name, password...)
238  // If email and name is changed, set it in the users record:
239  $be_user_data = $d['be_users'];
240  // Possibility to modify the transmitted values. Useful to do transformations, like RSA password decryption
241  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/setup/mod/index.php']['modifyUserDataBeforeSave'])) {
242  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/setup/mod/index.php']['modifyUserDataBeforeSave'] as $function) {
243  $params = ['be_user_data' => &$be_user_data];
244  GeneralUtility::callUserFunction($function, $params, $this);
245  }
246  }
247  $this->passwordIsSubmitted = (string)$be_user_data['password'] !== '';
248  $passwordIsConfirmed = $this->passwordIsSubmitted && $be_user_data['password'] === $be_user_data['password2'];
249  // Update the real name:
250  if ($be_user_data['realName'] !== $beUser->user['realName']) {
251  $beUser->user['realName'] = ($storeRec['be_users'][$beUserId]['realName'] = substr($be_user_data['realName'], 0, 80));
252  }
253  // Update the email address:
254  if ($be_user_data['email'] !== $beUser->user['email']) {
255  $beUser->user['email'] = ($storeRec['be_users'][$beUserId]['email'] = substr($be_user_data['email'], 0, 80));
256  }
257  // Update the password:
258  if ($passwordIsConfirmed) {
259  $currentPasswordHashed = $GLOBALS['BE_USER']->user['password'];
260  $saltFactory = \TYPO3\CMS\Saltedpasswords\Salt\SaltFactory::getSaltingInstance($currentPasswordHashed);
261  if ($saltFactory->checkPassword($be_user_data['passwordCurrent'], $currentPasswordHashed)) {
262  $this->passwordIsUpdated = self::PASSWORD_UPDATED;
263  $storeRec['be_users'][$beUserId]['password'] = $be_user_data['password'];
264  } else {
265  $this->passwordIsUpdated = self::PASSWORD_OLD_WRONG;
266  }
267  } else {
268  $this->passwordIsUpdated = self::PASSWORD_NOT_THE_SAME;
269  }
270 
271  $this->setAvatarFileUid($beUserId, $be_user_data['avatar'], $storeRec);
272 
273  $this->saveData = true;
274  }
275  // Inserts the overriding values.
276  $beUser->overrideUC();
277  $save_after = md5(serialize($beUser->uc));
278  // If something in the uc-array of the user has changed, we save the array...
279  if ($save_before != $save_after) {
280  $beUser->writeUC($beUser->uc);
281  $beUser->writelog(254, 1, 0, 1, 'Personal settings changed', []);
282  $this->setupIsUpdated = true;
283  }
284  // Persist data if something has changed:
285  if (!empty($storeRec) && $this->saveData) {
286  // Make instance of TCE for storing the changes.
288  $dataHandler = GeneralUtility::makeInstance(DataHandler::class);
289  // This is so the user can actually update his user record.
290  $isAdmin = $beUser->user['admin'];
291  $beUser->user['admin'] = 1;
292  $dataHandler->start($storeRec, [], $beUser);
293  // This is to make sure that the users record can be updated even if in another workspace. This is tolerated.
294  $dataHandler->bypassWorkspaceRestrictions = true;
295  $dataHandler->process_datamap();
296  unset($tce);
297  if ($this->passwordIsUpdated === self::PASSWORD_NOT_UPDATED || count($storeRec['be_users'][$beUserId]) > 1) {
298  $this->setupIsUpdated = true;
299  }
300  // Restore admin status after processing
301  $beUser->user['admin'] = $isAdmin;
302  }
303  }
304  }
305 
306  /******************************
307  *
308  * Rendering module
309  *
310  ******************************/
316  public function init()
317  {
318  $this->getLanguageService()->includeLLFile('EXT:setup/Resources/Private/Language/locallang.xlf');
319 
320  // Returns the script user - that is the REAL logged in user! ($GLOBALS[BE_USER] might be another user due to simulation!)
321  $scriptUser = $this->getRealScriptUserObj();
322 
323  $this->isAdmin = $scriptUser->isAdmin();
324  // Getting the 'override' values as set might be set in User TSconfig
325  $this->overrideConf = $this->getBackendUser()->getTSConfigProp('setup.override');
326  // Getting the disabled fields might be set in User TSconfig (eg setup.fields.password.disabled=1)
327  $this->tsFieldConf = $this->getBackendUser()->getTSConfigProp('setup.fields');
328  // id password is disabled, disable repeat of password too (password2)
329  if (isset($this->tsFieldConf['password.']) && $this->tsFieldConf['password.']['disabled']) {
330  $this->tsFieldConf['password2.']['disabled'] = 1;
331  $this->tsFieldConf['passwordCurrent.']['disabled'] = 1;
332  }
333  }
334 
340  protected function getJavaScript()
341  {
342  $javaScript = '';
343  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/setup/mod/index.php']['setupScriptHook'])) {
344  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/setup/mod/index.php']['setupScriptHook'] as $function) {
345  $params = [];
346  $javaScript .= GeneralUtility::callUserFunction($function, $params, $this);
347  }
348  }
349  return $javaScript;
350  }
351 
357  public function main()
358  {
359  $this->content .= '<form action="' . BackendUtility::getModuleUrl('user_setup') . '" method="post" id="SetupModuleController" name="usersetup" enctype="multipart/form-data">';
360  if ($this->languageUpdate) {
361  $this->moduleTemplate->addJavaScriptCode('languageUpdate', '
362  if (top && top.TYPO3.ModuleMenu.App) {
363  top.TYPO3.ModuleMenu.App.refreshMenu();
364  }
365  ');
366  }
367  if ($this->pagetreeNeedsRefresh) {
368  BackendUtility::setUpdateSignal('updatePageTree');
369  }
370  // Start page:
371  $this->moduleTemplate->getPageRenderer()->addJsFile('EXT:backend/Resources/Public/JavaScript/md5.js');
372  // Use a wrapper div
373  $this->content .= '<div id="user-setup-wrapper">';
374  // Load available backend modules
375  $this->loadModules = GeneralUtility::makeInstance(ModuleLoader::class);
376  $this->loadModules->observeWorkspaces = true;
377  $this->loadModules->load($GLOBALS['TBE_MODULES']);
378  $this->content .= $this->moduleTemplate->header($this->getLanguageService()->getLL('UserSettings'));
379  $this->addFlashMessages();
380 
381  // Render user switch
382  $this->content .= $this->renderSimulateUserSelectAndLabel();
383 
384  // Render the menu items
385  $menuItems = $this->renderUserSetup();
386  $this->content .= $this->moduleTemplate->getDynamicTabMenu($menuItems, 'user-setup', 1, false, false);
387  $formToken = $this->formProtection->generateToken('BE user setup', 'edit');
388  $this->content .= '<div>';
389  $this->content .= '<input type="hidden" name="simUser" value="' . (int)$this->simUser . '" />
390  <input type="hidden" name="formToken" value="' . htmlspecialchars($formToken) . '" />
391  <input type="hidden" value="1" name="data[save]" />
392  <input type="hidden" name="data[setValuesToDefault]" value="0" id="setValuesToDefault" />';
393  $this->content .= '</div>';
394  // End of wrapper div
395  $this->content .= '</div>';
396  // Setting up the buttons and markers for docheader
397  $this->getButtons();
398  // Build the <body> for the module
399  // Renders the module page
400  $this->moduleTemplate->setContent($this->content);
401  $this->content .= '</form>';
402  }
403 
412  public function mainAction(ServerRequestInterface $request, ResponseInterface $response)
413  {
414  $GLOBALS['SOBE'] = $this;
415  $this->simulateUser();
416  $this->storeIncomingData();
417  $this->init();
418  $this->main();
419 
420  $response->getBody()->write($this->moduleTemplate->renderContent());
421  return $response;
422  }
423 
427  protected function getButtons()
428  {
429  $buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
430  $cshButton = $buttonBar->makeHelpButton()
431  ->setModuleName('_MOD_user_setup')
432  ->setFieldName('');
433  $buttonBar->addButton($cshButton);
434 
435  $saveButton = $buttonBar->makeInputButton()
436  ->setName('data[save]')
437  ->setTitle($this->getLanguageService()->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:rm.saveDoc'))
438  ->setValue('1')
439  ->setForm('SetupModuleController')
440  ->setShowLabelText(true)
441  ->setIcon($this->moduleTemplate->getIconFactory()->getIcon('actions-document-save', Icon::SIZE_SMALL));
442 
443  $buttonBar->addButton($saveButton);
444  $shortcutButton = $buttonBar->makeShortcutButton()
445  ->setModuleName($this->moduleName);
446  $buttonBar->addButton($shortcutButton);
447  }
448 
449  /******************************
450  *
451  * Render module
452  *
453  ******************************/
454 
461  protected function renderUserSetup()
462  {
463  $html = '';
464  $result = [];
465  $firstTabLabel = '';
466  $code = [];
467  $fieldArray = $this->getFieldsFromShowItem();
468  $tabLabel = '';
469  foreach ($fieldArray as $fieldName) {
470  $config = $GLOBALS['TYPO3_USER_SETTINGS']['columns'][$fieldName];
471  if (isset($config['access']) && !$this->checkAccess($config)) {
472  continue;
473  }
474 
475  if (substr($fieldName, 0, 8) === '--div--;') {
476  if ($firstTabLabel === '') {
477  // First tab
478  $tabLabel = $this->getLabel(substr($fieldName, 8), '', false);
479  $firstTabLabel = $tabLabel;
480  } else {
481  $result[] = [
482  'label' => $tabLabel,
483  'content' => count($code) ? implode(LF, $code) : ''
484  ];
485  $tabLabel = $this->getLabel(substr($fieldName, 8), '', false);
486  $code = [];
487  }
488  continue;
489  }
490  $label = $this->getLabel($config['label'], $fieldName);
491  $label = $this->getCSH($config['csh'] ?: $fieldName, $label);
492  $type = $config['type'];
493  $class = $config['class'];
494  if ($type !== 'check') {
495  $class .= ' form-control';
496  }
497  $more = '';
498  if ($class) {
499  $more .= ' class="' . htmlspecialchars($class) . '"';
500  }
501  $style = $config['style'];
502  if ($style) {
503  $more .= ' style="' . htmlspecialchars($style) . '"';
504  }
505  if (isset($this->overrideConf[$fieldName])) {
506  $more .= ' disabled="disabled"';
507  }
508  $value = $config['table'] === 'be_users' ? $this->getBackendUser()->user[$fieldName] : $this->getBackendUser()->uc[$fieldName];
509  if (!$value && isset($config['default'])) {
510  $value = $config['default'];
511  }
512  $dataAdd = '';
513  if ($config['table'] === 'be_users') {
514  $dataAdd = '[be_users]';
515  }
516 
517  switch ($type) {
518  case 'text':
519  case 'email':
520  case 'password':
521  $noAutocomplete = '';
522  if ($type === 'password') {
523  $value = '';
524  $noAutocomplete = 'autocomplete="off" ';
525  $more .= ' data-rsa-encryption=""';
526  }
527  $html = '<input id="field_' . htmlspecialchars($fieldName) . '"
528  type="' . htmlspecialchars($type) . '"
529  name="data' . $dataAdd . '[' . htmlspecialchars($fieldName) . ']" ' .
530  $noAutocomplete .
531  'value="' . htmlspecialchars($value) . '" ' .
532  $more .
533  ' />';
534  break;
535  case 'check':
536  $html = $label . '<div class="checkbox"><label><input id="field_' . htmlspecialchars($fieldName) . '"
537  type="checkbox"
538  name="data' . $dataAdd . '[' . htmlspecialchars($fieldName) . ']"' .
539  ($value ? ' checked="checked"' : '') .
540  $more .
541  ' /></label></div>';
542  $label = '';
543  break;
544  case 'select':
545  if ($config['itemsProcFunc']) {
546  $html = GeneralUtility::callUserFunction($config['itemsProcFunc'], $config, $this);
547  } else {
548  $html = '<select id="field_' . htmlspecialchars($fieldName) . '"
549  name="data' . $dataAdd . '[' . htmlspecialchars($fieldName) . ']"' .
550  $more . '>' . LF;
551  foreach ($config['items'] as $key => $optionLabel) {
552  $html .= '<option value="' . htmlspecialchars($key) . '"' . ($value == $key ? ' selected="selected"' : '') . '>' . $this->getLabel($optionLabel, '', false) . '</option>' . LF;
553  }
554  $html .= '</select>';
555  }
556  break;
557  case 'user':
558  $html = GeneralUtility::callUserFunction($config['userFunc'], $config, $this);
559  break;
560  case 'button':
561  if ($config['onClick']) {
562  $onClick = $config['onClick'];
563  if ($config['onClickLabels']) {
564  foreach ($config['onClickLabels'] as $key => $labelclick) {
565  $config['onClickLabels'][$key] = $this->getLabel($labelclick, '', false);
566  }
567  $onClick = vsprintf($onClick, $config['onClickLabels']);
568  }
569  $html = '<br><input class="btn btn-default" type="button"
570  value="' . $this->getLabel($config['buttonlabel'], '', false) . '"
571  onclick="' . $onClick . '" />';
572  }
573  if (!empty($config['confirm'])) {
574  $confirmData = $config['confirmData'];
575  $html = '<br><input class="btn btn-default t3js-modal-trigger" type="button"'
576  . ' value="' . $this->getLabel($config['buttonlabel'], '', false) . '"'
577  . ' data-href="javascript:' . htmlspecialchars($confirmData['jsCodeAfterOk']) . '"'
578  . ' data-severity="warning"'
579  . ' data-title="' . $this->getLabel($config['label'], '', false) . '"'
580  . ' data-content="' . $this->getLabel($confirmData['message'], '', false) . '" />';
581  }
582  break;
583  case 'avatar':
584  // Get current avatar image
585  $html = '<br>';
586  $avatarFileUid = $this->getAvatarFileUid($this->getBackendUser()->user['uid']);
587 
588  if ($avatarFileUid) {
589  $defaultAvatarProvider = GeneralUtility::makeInstance(DefaultAvatarProvider::class);
590  $avatarImage = $defaultAvatarProvider->getImage($this->getBackendUser()->user, 32);
591  if ($avatarImage) {
592  $icon = '<span class="avatar"><span class="avatar-image">' .
593  '<img src="' . htmlspecialchars($avatarImage->getUrl(true)) . '"' .
594  ' width="' . (int)$avatarImage->getWidth() . '" ' .
595  'height="' . (int)$avatarImage->getHeight() . '" />' .
596  '</span></span>';
597  $html .= '<span class="pull-left" style="padding-right: 10px" id="image_' . htmlspecialchars($fieldName) . '">' . $icon . ' </span>';
598  }
599  }
600  $html .= '<input id="field_' . htmlspecialchars($fieldName) . '" type="hidden" ' .
601  'name="data' . $dataAdd . '[' . htmlspecialchars($fieldName) . ']"' . $more .
602  ' value="' . (int)$avatarFileUid . '" />';
603 
604  $html .= '<div class="btn-group">';
605  $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
606  if ($avatarFileUid) {
607  $html .=
608  '<a id="clear_button_' . htmlspecialchars($fieldName) . '" '
609  . 'onclick="clearExistingImage(); return false;" class="btn btn-default">'
610  . $iconFactory->getIcon('actions-delete', Icon::SIZE_SMALL)
611  . '</a>';
612  }
613  $html .=
614  '<a id="add_button_' . htmlspecialchars($fieldName) . '" class="btn btn-default btn-add-avatar"'
615  . ' onclick="openFileBrowser();return false;">'
616  . $iconFactory->getIcon('actions-insert-record', Icon::SIZE_SMALL)
617  . '</a></div>';
618 
619  $this->addAvatarButtonJs($fieldName);
620  break;
621  default:
622  $html = '';
623  }
624 
625  $code[] = '<div class="form-section"><div class="row"><div class="form-group col-md-12">' .
626  $label .
627  $html .
628  '</div></div></div>';
629  }
630 
631  $result[] = [
632  'label' => $tabLabel,
633  'content' => count($code) ? implode(LF, $code) : ''
634  ];
635  return $result;
636  }
637 
638  /******************************
639  *
640  * Helper functions
641  *
642  ******************************/
649  protected function getRealScriptUserObj()
650  {
651  return is_object($this->OLD_BE_USER) ? $this->OLD_BE_USER : $this->getBackendUser();
652  }
653 
659  public function renderLanguageSelect()
660  {
661  $languageOptions = [];
662  // Compile the languages dropdown
663  $langDefault = htmlspecialchars($this->getLanguageService()->getLL('lang_default'));
664  $languageOptions[$langDefault] = '<option value=""' . ($this->getBackendUser()->uc['lang'] === '' ? ' selected="selected"' : '') . '>' . $langDefault . '</option>';
665  // Traverse the number of languages
667  $locales = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Localization\Locales::class);
668  $languages = $locales->getLanguages();
669  foreach ($languages as $locale => $name) {
670  if ($locale !== 'default') {
671  $defaultName = isset($GLOBALS['LOCAL_LANG']['default']['lang_' . $locale]) ? $GLOBALS['LOCAL_LANG']['default']['lang_' . $locale][0]['source'] : $name;
672  $localizedName = htmlspecialchars($this->getLanguageService()->getLL('lang_' . $locale));
673  if ($localizedName === '') {
674  $localizedName = htmlspecialchars($name);
675  }
676  $localLabel = ' - [' . htmlspecialchars($defaultName) . ']';
677  $available = is_dir(PATH_typo3conf . 'l10n/' . $locale);
678  if ($available) {
679  $languageOptions[$defaultName] = '<option value="' . $locale . '"' . ($this->getBackendUser()->uc['lang'] === $locale ? ' selected="selected"' : '') . '>' . $localizedName . $localLabel . '</option>';
680  }
681  }
682  }
683  ksort($languageOptions);
684  $languageCode = '
685  <select id="field_lang" name="data[lang]" class="form-control">' . implode('', $languageOptions) . '
686  </select>';
687  if ($this->getBackendUser()->uc['lang'] && !@is_dir((PATH_typo3conf . 'l10n/' . $this->getBackendUser()->uc['lang']))) {
688  // TODO: The text constants have to be moved into language files
689  $languageUnavailableWarning = 'The selected language "' . htmlspecialchars($this->getLanguageService()->getLL('lang_' . $this->getBackendUser()->uc['lang'])) . '" is not available before the language files are installed.&nbsp;&nbsp;<br />&nbsp;&nbsp;' . ($this->getBackendUser()->isAdmin() ? 'You can use the Language module to easily download new language files.' : 'Please ask your system administrator to do this.');
690  $languageCode = '<br /><span class="label label-danger">' . $languageUnavailableWarning . '</span><br /><br />' . $languageCode;
691  }
692  return $languageCode;
693  }
694 
703  public function renderStartModuleSelect($params, $pObj)
704  {
705  // Load available backend modules
706  $this->loadModules = GeneralUtility::makeInstance(ModuleLoader::class);
707  $this->loadModules->observeWorkspaces = true;
708  $this->loadModules->load($GLOBALS['TBE_MODULES']);
709  $startModuleSelect = '<option value="">' . htmlspecialchars($this->getLanguageService()->getLL('startModule.firstInMenu')) . '</option>';
710  foreach ($pObj->loadModules->modules as $mainMod => $modData) {
711  if (!empty($modData['sub']) && is_array($modData['sub'])) {
712  $modules = '';
713  foreach ($modData['sub'] as $subData) {
714  $modName = $subData['name'];
715  $modules .= '<option value="' . htmlspecialchars($modName) . '"';
716  $modules .= $this->getBackendUser()->uc['startModule'] === $modName ? ' selected="selected"' : '';
717  $modules .= '>' . htmlspecialchars($this->getLanguageService()->sL($this->loadModules->getLabelsForModule($modName)['title'])) . '</option>';
718  }
719  $groupLabel = htmlspecialchars($this->getLanguageService()->sL($this->loadModules->getLabelsForModule($mainMod)['title']));
720  $startModuleSelect .= '<optgroup label="' . htmlspecialchars($groupLabel) . '">' . $modules . '</optgroup>';
721  }
722  }
723  return '<select id="field_startModule" name="data[startModule]" class="form-control">' . $startModuleSelect . '</select>';
724  }
725 
732  public function simulateUser()
733  {
734  // If admin, allow simulation of another user
735  $this->simUser = 0;
736  $this->simulateSelector = '';
737  unset($this->OLD_BE_USER);
738  if ($this->getBackendUser()->isAdmin()) {
739  $this->simUser = (int)GeneralUtility::_GP('simUser');
740  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('be_users');
741  $users = $queryBuilder
742  ->select('*')
743  ->from('be_users')
744  ->where(
745  $queryBuilder->expr()->neq(
746  'uid',
747  $queryBuilder->createNamedParameter($this->getBackendUser()->user['uid'], \PDO::PARAM_INT)
748  ),
749  $queryBuilder->expr()->notLike(
750  'username',
751  $queryBuilder->createNamedParameter(
752  $queryBuilder->escapeLikeWildcards('_cli_') . '%',
753  \PDO::PARAM_STR
754  )
755  )
756  )
757  ->orderBy('username')
758  ->execute()
759  ->fetchAll();
760  $opt = [];
761  foreach ($users as $rr) {
762  $label = $rr['username'] . ($rr['realName'] ? ' (' . $rr['realName'] . ')' : '');
763  $opt[] = '<option value="' . (int)$rr['uid'] . '"' . ($this->simUser === (int)$rr['uid'] ? ' selected="selected"' : '') . '>' . htmlspecialchars($label) . '</option>';
764  }
765  if (!empty($opt)) {
766  $this->simulateSelector = '<select id="field_simulate" class="form-control" name="simulateUser" onchange="window.location.href=' . GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('user_setup') . '&simUser=') . '+this.options[this.selectedIndex].value;"><option></option>' . implode('', $opt) . '</select>';
767  }
768  }
769  // This can only be set if the previous code was executed.
770  if ($this->simUser > 0) {
771  // Save old user...
772  $this->OLD_BE_USER = $this->getBackendUser();
773  unset($GLOBALS['BE_USER']);
774  // Unset current
775  // New backend user object
776  $BE_USER = GeneralUtility::makeInstance(BackendUserAuthentication::class);
777  $BE_USER->setBeUserByUid($this->simUser);
778  $BE_USER->fetchGroupData();
779  $BE_USER->backendSetUC();
780  // Must do this, because unsetting $BE_USER before apparently unsets the reference to the global variable by this name!
781  $GLOBALS['BE_USER'] = $BE_USER;
782  }
783  }
784 
790  protected function renderSimulateUserSelectAndLabel()
791  {
792  if ($this->simulateSelector === '') {
793  return '';
794  }
795 
796  return '<div class="form-inline"><div class="form-group"><p>'
797  . '<label for="field_simulate" style="margin-right: 20px;">'
798  . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:simulate'))
799  . '</label>'
800  . $this->simulateSelector
801  . '</p></div></div>';
802  }
803 
810  protected function checkAccess(array $config)
811  {
812  $access = $config['access'];
813 
814  if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['setup']['accessLevelCheck'][$access])) {
815  if (class_exists($access)) {
816  $accessObject = GeneralUtility::makeInstance($access);
817  if (method_exists($accessObject, 'accessLevelCheck')) {
818  // Initialize vars. If method fails, $set will be set to FALSE
819  return $accessObject->accessLevelCheck($config);
820  }
821  }
822  } elseif ($access == 'admin') {
823  return $this->isAdmin;
824  }
825 
826  return false;
827  }
828 
837  protected function getLabel($str, $key = '', $addLabelTag = true)
838  {
839  if (substr($str, 0, 4) === 'LLL:') {
840  $out = htmlspecialchars($this->getLanguageService()->sL($str));
841  } else {
842  $out = htmlspecialchars($str);
843  }
844  if (isset($this->overrideConf[$key ?: $str])) {
845  $out = '<span style="color:#999999">' . $out . '</span>';
846  }
847  if ($addLabelTag) {
848  $out = '<label>' . $out . '</label>';
849  }
850  return $out;
851  }
852 
860  protected function getCSH($str, $label)
861  {
862  $context = '_MOD_user_setup';
863  $field = $str;
864  $strParts = explode(':', $str);
865  if (count($strParts) > 1) {
866  // Setting comes from another extension
867  $context = $strParts[0];
868  $field = $strParts[1];
869  } elseif ($str !== 'language' && $str !== 'simuser' && $str !== 'reset') {
870  $field = 'option_' . $str;
871  }
872  return BackendUtility::wrapInHelp($context, $field, $label);
873  }
874 
881  protected function getFieldsFromShowItem()
882  {
883  $allowedFields = GeneralUtility::trimExplode(',', $GLOBALS['TYPO3_USER_SETTINGS']['showitem'], true);
884  if (!is_array($this->tsFieldConf)) {
885  return $allowedFields;
886  }
887  foreach ($this->tsFieldConf as $fieldName => $userTsFieldConfig) {
888  if (!empty($userTsFieldConfig['disabled'])) {
889  $fieldName = rtrim($fieldName, '.');
890  $key = array_search($fieldName, $allowedFields);
891  if ($key !== false) {
892  unset($allowedFields[$key]);
893  }
894  }
895  }
896  return $allowedFields;
897  }
898 
905  protected function getAvatarFileUid($beUserId)
906  {
907  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_file_reference');
908  $file = $queryBuilder
909  ->select('uid_local')
910  ->from('sys_file_reference')
911  ->where(
912  $queryBuilder->expr()->eq(
913  'tablenames',
914  $queryBuilder->createNamedParameter('be_users', \PDO::PARAM_STR)
915  ),
916  $queryBuilder->expr()->eq(
917  'fieldname',
918  $queryBuilder->createNamedParameter('avatar', \PDO::PARAM_STR)
919  ),
920  $queryBuilder->expr()->eq(
921  'table_local',
922  $queryBuilder->createNamedParameter('sys_file', \PDO::PARAM_STR)
923  ),
924  $queryBuilder->expr()->eq(
925  'uid_foreign',
926  $queryBuilder->createNamedParameter($beUserId, \PDO::PARAM_INT)
927  )
928  )
929  ->execute()
930  ->fetchColumn();
931  return (int)$file;
932  }
933 
941  protected function setAvatarFileUid($beUserId, $fileUid, array &$storeRec)
942  {
943 
944  // Update is only needed when new fileUid is set
945  if ((int)$fileUid === $this->getAvatarFileUid($beUserId)) {
946  return;
947  }
948 
949  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_file_reference');
950  $queryBuilder->getRestrictions()->removeAll();
951  $queryBuilder
952  ->delete('sys_file_reference')
953  ->where(
954  $queryBuilder->expr()->eq(
955  'tablenames',
956  $queryBuilder->createNamedParameter('be_users', \PDO::PARAM_STR)
957  ),
958  $queryBuilder->expr()->eq(
959  'fieldname',
960  $queryBuilder->createNamedParameter('avatar', \PDO::PARAM_STR)
961  ),
962  $queryBuilder->expr()->eq(
963  'table_local',
964  $queryBuilder->createNamedParameter('sys_file', \PDO::PARAM_STR)
965  ),
966  $queryBuilder->expr()->eq(
967  'uid_foreign',
968  $queryBuilder->createNamedParameter($beUserId, \PDO::PARAM_INT)
969  )
970  )
971  ->execute();
972 
973  // Create new reference
974  if ($fileUid) {
975 
976  // Get file object
977  try {
978  $file = ResourceFactory::getInstance()->getFileObject($fileUid);
979  } catch (FileDoesNotExistException $e) {
980  $file = false;
981  }
982 
983  // Check if user is allowed to use the image (only when not in simulation mode)
984  if ($file && $this->simUser === 0 && !$file->getStorage()->checkFileActionPermission('read', $file)) {
985  $file = false;
986  }
987 
988  // Check if extension is allowed
989  if ($file && GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $file->getExtension())) {
990 
991  // Create new file reference
992  $storeRec['sys_file_reference']['NEW1234'] = [
993  'uid_local' => (int)$fileUid,
994  'uid_foreign' => (int)$beUserId,
995  'tablenames' => 'be_users',
996  'fieldname' => 'avatar',
997  'pid' => 0,
998  'table_local' => 'sys_file',
999  ];
1000  $storeRec['be_users'][(int)$beUserId]['avatar'] = 'NEW1234';
1001  }
1002  }
1003  }
1004 
1010  protected function addAvatarButtonJs($fieldName)
1011  {
1012  $this->moduleTemplate->addJavaScriptCode('avatar-button', '
1013  var browserWin="";
1014 
1015  function openFileBrowser() {
1016  var url = ' . GeneralUtility::quoteJSvalue(BackendUtility::getModuleUrl('wizard_element_browser', ['mode' => 'file', 'bparams' => '||||dummy|setFileUid'])) . ';
1017  browserWin = window.open(url,"Typo3WinBrowser","height=650,width=800,status=0,menubar=0,resizable=1,scrollbars=1");
1018  browserWin.focus();
1019  }
1020 
1021  function clearExistingImage() {
1022  TYPO3.jQuery(' . GeneralUtility::quoteJSvalue('#image_' . htmlspecialchars($fieldName)) . ').hide();
1023  TYPO3.jQuery(' . GeneralUtility::quoteJSvalue('#clear_button_' . htmlspecialchars($fieldName)) . ').hide();
1024  TYPO3.jQuery(' . GeneralUtility::quoteJSvalue('#field_' . htmlspecialchars($fieldName)) . ').val(\'\');
1025  }
1026 
1027  function setFileUid(field, value, fileUid) {
1028  clearExistingImage();
1029  TYPO3.jQuery(' . GeneralUtility::quoteJSvalue('#field_' . htmlspecialchars($fieldName)) . ').val(fileUid);
1030  TYPO3.jQuery(' . GeneralUtility::quoteJSvalue('#add_button_' . htmlspecialchars($fieldName)) . ').removeClass(\'btn-default\').addClass(\'btn-info\');
1031 
1032  browserWin.close();
1033  }
1034  ');
1035  }
1036 
1042  protected function getBackendUser()
1043  {
1044  return $GLOBALS['BE_USER'];
1045  }
1046 
1052  protected function getLanguageService()
1053  {
1054  return $GLOBALS['LANG'];
1055  }
1056 
1062  protected function addFlashMessages()
1063  {
1064  $flashMessages = [];
1065 
1066  // Show if setup was saved
1067  if ($this->setupIsUpdated && !$this->settingsAreResetToDefault) {
1068  $flashMessages[] = $this->getFlashMessage('setupWasUpdated', 'UserSettings');
1069  }
1070 
1071  // Show if temporary data was cleared
1072  if ($this->settingsAreResetToDefault) {
1073  $flashMessages[] = $this->getFlashMessage('settingsAreReset', 'resetConfiguration');
1074  }
1075 
1076  // Notice
1077  if ($this->setupIsUpdated || $this->settingsAreResetToDefault) {
1078  $flashMessages[] = $this->getFlashMessage('activateChanges', '', FlashMessage::INFO);
1079  }
1080 
1081  // If password is updated, output whether it failed or was OK.
1082  if ($this->passwordIsSubmitted) {
1083  $flashMessage = null;
1084  switch ($this->passwordIsUpdated) {
1085  case self::PASSWORD_OLD_WRONG:
1086  $flashMessages[] = $this->getFlashMessage('oldPassword_failed', 'newPassword', FlashMessage::ERROR);
1087  break;
1088  case self::PASSWORD_NOT_THE_SAME:
1089  $flashMessages[] = $this->getFlashMessage('newPassword_failed', 'newPassword', FlashMessage::ERROR);
1090  break;
1091  case self::PASSWORD_UPDATED:
1092  $flashMessages[] = $this->getFlashMessage('newPassword_ok', 'newPassword');
1093  break;
1094  }
1095  }
1096  if (!empty($flashMessages)) {
1097  $this->enqueueFlashMessages($flashMessages);
1098  }
1099  }
1100 
1106  protected function enqueueFlashMessages(array $flashMessages)
1107  {
1108  $flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
1109  $defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
1110  foreach ($flashMessages as $flashMessage) {
1111  $defaultFlashMessageQueue->enqueue($flashMessage);
1112  }
1113  }
1114 
1121  protected function getFlashMessage($message, $title, $severity = FlashMessage::OK)
1122  {
1123  $title = !empty($title) ? $this->getLanguageService()->getLL($title) : ' ';
1125  FlashMessage::class,
1126  $this->getLanguageService()->getLL($message),
1127  $title,
1128  $severity
1129  );
1130  }
1131 }
getFlashMessage($message, $title, $severity=FlashMessage::OK)
static trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
setAvatarFileUid($beUserId, $fileUid, array &$storeRec)
mainAction(ServerRequestInterface $request, ResponseInterface $response)
static get($classNameOrType= 'default',...$constructorArguments)
static getSaltingInstance($saltedHash= '', $mode=TYPO3_MODE)
Definition: SaltFactory.php:83
if(TYPO3_MODE=== 'BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
static makeInstance($className,...$constructorArguments)
static callUserFunction($funcName, &$params, &$ref, $_= '', $errorMode=0)