‪TYPO3CMS  ‪main
SetupModuleController.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=1);
4 
5 /*
6  * This file is part of the TYPO3 CMS project.
7  *
8  * It is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU General Public License, either version 2
10  * of the License, or any later version.
11  *
12  * For the full copyright and license information, please read the
13  * LICENSE.txt file that was distributed with this source code.
14  *
15  * The TYPO3 project - inspiring people to share!
16  */
17 
19 
20 use Psr\EventDispatcher\EventDispatcherInterface;
21 use Psr\Http\Message\ResponseInterface;
22 use Psr\Http\Message\ServerRequestInterface;
29 use TYPO3\CMS\Backend\Utility\BackendUtility;
40 use TYPO3\CMS\Core\Imaging\IconSize;
52 use ‪TYPO3\CMS\Core\SysLog\Action\Setting as SystemLogSettingAction;
53 use ‪TYPO3\CMS\Core\SysLog\Error as SystemLogErrorClassification;
54 use ‪TYPO3\CMS\Core\SysLog\Type as SystemLogType;
58 
64 #[AsController]
66 {
67  protected const ‪PASSWORD_NOT_UPDATED = 0;
68  protected const ‪PASSWORD_UPDATED = 1;
69  protected const ‪PASSWORD_NOT_THE_SAME = 2;
70  protected const ‪PASSWORD_OLD_WRONG = 3;
71  protected const ‪PASSWORD_POLICY_FAILED = 4;
72 
73  protected array ‪$overrideConf = [];
74  protected bool ‪$languageUpdate = false;
75  protected bool ‪$pagetreeNeedsRefresh = false;
76  protected array ‪$tsFieldConf = [];
78  protected bool ‪$passwordIsSubmitted = false;
79  protected bool ‪$setupIsUpdated = false;
80  protected bool ‪$settingsAreResetToDefault = false;
81 
83 
84  public function ‪__construct(
85  protected readonly EventDispatcherInterface $eventDispatcher,
86  protected readonly ‪MfaProviderRegistry $mfaProviderRegistry,
87  protected readonly ‪IconFactory $iconFactory,
88  protected readonly ‪PageRenderer $pageRenderer,
89  protected readonly ‪ModuleTemplateFactory $moduleTemplateFactory,
90  protected readonly ‪LanguageServiceFactory $languageServiceFactory,
91  protected readonly ‪ModuleProvider $moduleProvider,
92  protected readonly ‪UriBuilder $uriBuilder,
93  protected readonly ‪FormProtectionFactory $formProtectionFactory,
94  protected readonly ‪Locales $locales,
95  ) {
96  $passwordPolicy = ‪$GLOBALS['TYPO3_CONF_VARS']['BE']['passwordPolicy'] ?? 'default';
97 
98  $action = PasswordPolicyAction::UPDATE_USER_PASSWORD;
99  if ($this->‪getBackendUser()->getOriginalUserIdWhenInSwitchUserMode()) {
100  $action = PasswordPolicyAction::UPDATE_USER_PASSWORD_SWITCH_USER_MODE;
101  }
102 
103  $this->passwordPolicyValidator = GeneralUtility::makeInstance(
104  PasswordPolicyValidator::class,
105  $action,
106  is_string($passwordPolicy) ? $passwordPolicy : ''
107  );
108  }
109 
113  public function ‪mainAction(ServerRequestInterface $request): ResponseInterface
114  {
115  $view = $this->‪initialize($request);
116  $this->‪storeIncomingData($request);
117  if ($this->pagetreeNeedsRefresh) {
118  BackendUtility::setUpdateSignal('updatePageTree');
119  }
120  $formProtection = $this->formProtectionFactory->createFromRequest($request);
121  $this->‪addFlashMessages($view);
122  $this->‪getButtons($view);
123  $view->assignMultiple([
124  'isLanguageUpdate' => $this->languageUpdate,
125  'menuItems' => $this->‪renderUserSetup(),
126  'menuId' => 'DTM-375167ed176e8c9caf4809cee7df156c',
127  'formToken' => $formProtection->generateToken('BE user setup', 'edit'),
128  ]);
129  return $view->renderResponse('Main');
130  }
131 
135  protected function ‪initialize(ServerRequestInterface $request): ‪ModuleTemplate
136  {
137  $languageService = $this->‪getLanguageService();
138  $backendUser = $this->‪getBackendUser();
139  $view = $this->moduleTemplateFactory->create($request);
140  $this->pageRenderer->loadJavaScriptModule('@typo3/backend/modal.js');
141  $this->pageRenderer->loadJavaScriptModule('@typo3/backend/form-engine.js');
142  $this->pageRenderer->loadJavaScriptModule('@typo3/setup/setup-module.js');
144  $this->pageRenderer->addInlineSetting('FormEngine', 'formName', 'editform');
145  $this->pageRenderer->addInlineLanguageLabelArray([
146  'FormEngine.remainingCharacters' => $languageService->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:labels.remainingCharacters'),
147  ]);
148  $view->setTitle($languageService->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:UserSettings'));
149  // Getting the 'override' values as set might be set in user TSconfig
150  $this->overrideConf = $backendUser->getTSConfig()['setup.']['override.'] ?? [];
151  // Getting the disabled fields might be set in user TSconfig (eg setup.fields.password.disabled=1)
152  $this->tsFieldConf = $backendUser->getTSConfig()['setup.']['fields.'] ?? [];
153  // if password is disabled, disable repeat of password too (password2)
154  if ($this->tsFieldConf['password.']['disabled'] ?? false) {
155  $this->tsFieldConf['password2.']['disabled'] = 1;
156  $this->tsFieldConf['passwordCurrent.']['disabled'] = 1;
157  }
158  return $view;
159  }
160 
161  protected function ‪processAdditionalJavaScriptModules(): void
162  {
163  $event = new ‪AddJavaScriptModulesEvent();
164  $event = $this->eventDispatcher->dispatch($event);
165  foreach ($event->getJavaScriptModules() as $specifier) {
166  $this->pageRenderer->loadJavaScriptModule($specifier);
167  }
168  }
169 
173  protected function ‪storeIncomingData(ServerRequestInterface $request): void
174  {
175  $postData = $request->getParsedBody();
176  if (!is_array($postData) || empty($postData)) {
177  return;
178  }
179 
180  $formProtection = $this->formProtectionFactory->createFromRequest($request);
181  // First check if something is submitted in the data-array from POST vars
182  $d = $postData['data'] ?? null;
183  $columns = ‪$GLOBALS['TYPO3_USER_SETTINGS']['columns'];
184  $backendUser = $this->‪getBackendUser();
185  $beUserId = (int)$backendUser->user['uid'];
186  $storeRec = [];
187  $doSaveData = false;
188  $fieldList = $this->getFieldsFromShowItem();
189  if (is_array($d) && $formProtection->validateToken((string)($postData['formToken'] ?? ''), 'BE user setup', 'edit')) {
190  // UC hashed before applying changes
191  $save_before = md5(serialize($backendUser->uc));
192  // PUT SETTINGS into the ->uc array:
193  // Reload left frame when switching BE language
194  if (isset($d['be_users']['lang']) && $d['be_users']['lang'] !== $backendUser->user['lang']) {
195  $this->languageUpdate = true;
196  }
197  // Reload pagetree if the title length is changed
198  if (isset($d['titleLen']) && $d['titleLen'] !== $backendUser->uc['titleLen']) {
199  $this->pagetreeNeedsRefresh = true;
200  }
201  if ($d['setValuesToDefault']) {
202  // If every value should be default
203  $backendUser->resetUC();
204  $this->settingsAreResetToDefault = true;
205  } elseif ($d['save']) {
206  // Save all submitted values if they are no array (arrays are with table=be_users) and exists in $GLOBALS['TYPO3_USER_SETTINGS'][columns]
207  foreach ($columns as $field => $config) {
208  if (!in_array($field, $fieldList, true)) {
209  continue;
210  }
211  if (($config['table'] ?? '') === 'be_users' && !in_array($field, ['password', 'password2', 'passwordCurrent', 'email', 'realName', 'admin', 'avatar'], true)) {
212  if (!isset($config['access']) || $this->‪checkAccess($config) && ($backendUser->user[$field] !== $d['be_users'][$field])) {
213  if (($config['type'] ?? false) === 'check') {
214  $fieldValue = isset($d['be_users'][$field]) ? 1 : 0;
215  } else {
216  $fieldValue = $d['be_users'][$field];
217  }
218  $storeRec['be_users'][$beUserId][$field] = $fieldValue;
219  $backendUser->user[$field] = $fieldValue;
220  }
221  }
222  if (($config['type'] ?? false) === 'check') {
223  $backendUser->uc[$field] = isset($d[$field]) ? 1 : 0;
224  } else {
225  $backendUser->uc[$field] = htmlspecialchars($d[$field] ?? '');
226  }
227  }
228  // Personal data for the users be_user-record (email, name, password...)
229  // If email and name is changed, set it in the users record:
230  $be_user_data = $d['be_users'];
231  // Possibility to modify the transmitted values. Useful to do transformations, like RSA password decryption
232  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ext/setup/mod/index.php']['modifyUserDataBeforeSave'] ?? [] as $function) {
233  $params = ['be_user_data' => &$be_user_data];
234  GeneralUtility::callUserFunction($function, $params, $this);
235  }
236  $this->passwordIsSubmitted = (string)$be_user_data['password'] !== '';
237  $passwordIsConfirmed = $this->passwordIsSubmitted && $be_user_data['password'] === $be_user_data['password2'];
238 
239  // Validate password against password policy
240  $contextData = new ‪ContextData(
241  loginMode: 'BE',
242  currentPasswordHash: $this->‪getBackendUser()->user['password'],
243  newUserFullName: $be_user_data['realName']
244  );
245  $contextData->setData('currentUsername', $this->‪getBackendUser()->user['username']);
246  $event = $this->eventDispatcher->dispatch(
248  $contextData,
249  $be_user_data,
250  self::class
251  )
252  );
253  $contextData = $event->getContextData();
254 
255  $passwordValid = true;
256  if ($passwordIsConfirmed &&
257  !$this->passwordPolicyValidator->isValidPassword($be_user_data['password'], $contextData)
258  ) {
259  $passwordValid = false;
260  $this->passwordIsUpdated = ‪self::PASSWORD_POLICY_FAILED;
261  }
262 
263  // Update the real name:
264  if (isset($be_user_data['realName']) && $be_user_data['realName'] !== $backendUser->user['realName']) {
265  $backendUser->user['realName'] = ($storeRec['be_users'][$beUserId]['realName'] = substr($be_user_data['realName'], 0, 80));
266  }
267  // Update the email address:
268  if (isset($be_user_data['email']) && $be_user_data['email'] !== $backendUser->user['email']) {
269  $backendUser->user['email'] = ($storeRec['be_users'][$beUserId]['email'] = substr($be_user_data['email'], 0, 255));
270  }
271  // Update the password:
272  if ($passwordIsConfirmed && $passwordValid) {
273  if ($backendUser->isAdmin()) {
274  $passwordOk = true;
275  } else {
276  $currentPasswordHashed = $backendUser->user['password'];
277  $passwordOk = false;
278  $saltFactory = GeneralUtility::makeInstance(PasswordHashFactory::class);
279  try {
280  $hashInstance = $saltFactory->get($currentPasswordHashed, 'BE');
281  $passwordOk = $hashInstance->checkPassword($be_user_data['passwordCurrent'], $currentPasswordHashed);
282  } catch (‪InvalidPasswordHashException $e) {
283  // Could not find hash class responsible for existing password. This is a
284  // misconfiguration and user can not change its password.
285  }
286  }
287  if ($passwordOk) {
288  $this->passwordIsUpdated = ‪self::PASSWORD_UPDATED;
289  $storeRec['be_users'][$beUserId]['password'] = $be_user_data['password'];
290  } else {
291  $this->passwordIsUpdated = ‪self::PASSWORD_OLD_WRONG;
292  }
293  } elseif ($passwordIsConfirmed) {
294  $this->passwordIsUpdated = ‪self::PASSWORD_POLICY_FAILED;
295  } else {
296  $this->passwordIsUpdated = ‪self::PASSWORD_NOT_THE_SAME;
297  }
298 
299  $this->‪setAvatarFileUid($beUserId, $be_user_data['avatar'], $storeRec);
300 
301  $doSaveData = true;
302  }
303  // Inserts the overriding values.
304  $backendUser->overrideUC();
305  $save_after = md5(serialize($backendUser->uc));
306  // If something in the uc-array of the user has changed, we save the array...
307  if ($save_before != $save_after) {
308  $backendUser->writeUC();
309  $backendUser->writelog(SystemLogType::SETTING, SystemLogSettingAction::CHANGE, SystemLogErrorClassification::MESSAGE, 1, 'Personal settings changed', []);
310  $this->setupIsUpdated = true;
311  }
312  // Persist data if something has changed:
313  if (!empty($storeRec) && $doSaveData) {
314  // Set user to admin to circumvent DataHandler restrictions.
315  // Not using isAdmin() to fetch the original value, just in case it has been boolean casted.
316  $savedUserAdminState = $backendUser->user['admin'];
317  $backendUser->user['admin'] = true;
318  // Make dedicated instance of TCE for storing the changes.
319  $dataHandler = GeneralUtility::makeInstance(DataHandler::class);
320  $dataHandler->start($storeRec, [], $backendUser);
321  // This is to make sure that the users record can be updated even if in another workspace. This is tolerated.
322  $dataHandler->bypassWorkspaceRestrictions = true;
323  $dataHandler->process_datamap();
324  // reset the user record admin flag to previous value, just in case it gets used any further.
325  $backendUser->user['admin'] = $savedUserAdminState;
326  if ($this->passwordIsUpdated === self::PASSWORD_NOT_UPDATED || count($storeRec['be_users'][$beUserId]) > 1) {
327  $this->setupIsUpdated = true;
328  }
329  BackendUtility::setUpdateSignal('updateTopbar');
330  }
331  }
332  }
333 
337  protected function ‪getButtons(‪ModuleTemplate $view): void
338  {
339  $buttonBar = $view->‪getDocHeaderComponent()->getButtonBar();
340 
341  $saveButton = $buttonBar->makeInputButton()
342  ->setName('data[save]')
343  ->setTitle($this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_core.xlf:rm.saveDoc'))
344  ->setValue('1')
345  ->setForm('SetupModuleController')
346  ->setShowLabelText(true)
347  ->setIcon($this->iconFactory->getIcon('actions-document-save', IconSize::SMALL));
348 
349  $buttonBar->addButton($saveButton);
350  $shortcutButton = $buttonBar->makeShortcutButton()
351  ->setRouteIdentifier('user_setup')
352  ->setDisplayName($this->‪getLanguageService()->sL('LLL:EXT:setup/Resources/Private/Language/locallang_mod.xlf:mlang_labels_tablabel'));
353  $buttonBar->addButton($shortcutButton);
354  }
355 
362  protected function ‪renderUserSetup(): array
363  {
364  $backendUser = $this->‪getBackendUser();
365  $html = '';
366  $result = [];
367  $firstTabLabel = '';
368  $code = [];
369  $fieldArray = $this->‪getFieldsFromShowItem();
370  $tabLabel = '';
371  foreach ($fieldArray as $fieldName) {
372  if (str_starts_with($fieldName, '--div--;')) {
373  if ($firstTabLabel === '') {
374  // First tab
375  $tabLabel = $this->‪getLabel(substr($fieldName, 8), '', false);
376  $firstTabLabel = $tabLabel;
377  } else {
378  $result[] = [
379  'label' => $tabLabel,
380  'content' => count($code) ? implode(LF, $code) : '',
381  ];
382  $tabLabel = $this->‪getLabel(substr($fieldName, 8), '', false);
383  $code = [];
384  }
385  continue;
386  }
387 
388  $config = ‪$GLOBALS['TYPO3_USER_SETTINGS']['columns'][$fieldName] ?? null;
389  if ($config && isset($config['access']) && !$this->‪checkAccess($config)) {
390  continue;
391  }
392 
393  $label = $this->‪getLabel($config['label'] ?? '', $fieldName);
394 
395  $type = $config['type'] ?? '';
396  $class = $config['class'] ?? '';
397  if ($type !== 'check' && $type !== 'select') {
398  $class .= ' form-control';
399  }
400  if ($type === 'select') {
401  $class .= ' form-select';
402  }
403  $more = '';
404  if ($class) {
405  $more .= ' class="' . htmlspecialchars($class) . '"';
406  }
407  $style = $config['style'] ?? '';
408  if ($style) {
409  $more .= ' style="' . htmlspecialchars($style) . '"';
410  }
411  if (isset($this->overrideConf[$fieldName])) {
412  $more .= ' disabled="disabled"';
413  }
414  $isBeUsersTable = ($config['table'] ?? false) === 'be_users';
415  $value = $isBeUsersTable ? ($backendUser->user[$fieldName] ?? false) : ($backendUser->uc[$fieldName] ?? false);
416  if (!$value && isset($config['default'])) {
417  $value = $config['default'];
418  }
419  $dataAdd = $isBeUsersTable ? '[be_users]' : '';
420 
421  switch ($type) {
422  case 'text':
423  case 'number':
424  case 'email':
425  case 'password':
426  $autocomplete = '';
427 
428  $maxLength = $config['max'] ?? 0;
429  if ((int)$maxLength > 0) {
430  $more .= ' maxlength="' . (int)$maxLength . '"';
431  }
432 
433  if ($type === 'password') {
434  $value = '';
435  $autocomplete = 'autocomplete="new-password" ';
436  }
437 
438  if ($fieldName === 'realName') {
439  $autocomplete = 'autocomplete="name" ';
440  }
441 
442  if ($fieldName === 'email') {
443  $autocomplete = 'autocomplete="email" ';
444  }
445 
446  $addPasswordRequirementsDescription = false;
447  if ($fieldName === 'password' && $this->passwordPolicyValidator->isEnabled() && $this->passwordPolicyValidator->hasRequirements()) {
448  $addPasswordRequirementsDescription = true;
449  }
450 
451  $html = '<input id="field_' . htmlspecialchars($fieldName) . '"
452  type="' . htmlspecialchars($type) . '" ' .
453  ($addPasswordRequirementsDescription ? 'aria-describedby="description_' . htmlspecialchars($fieldName) . '" ' : '') .
454  'name="data' . $dataAdd . '[' . htmlspecialchars($fieldName) . ']" ' .
455  $autocomplete .
456  'value="' . htmlspecialchars((string)$value) . '" ' .
457  $more .
458  ' />';
459 
460  if ($addPasswordRequirementsDescription) {
461  $description = $this->‪getLanguageService()->sL('LLL:EXT:core/Resources/Private/Language/locallang_password_policy.xlf:passwordRequirements.description');
462  $html .= '<div id="description_' . htmlspecialchars($fieldName) . '"><p class="mt-2 mb-1 text-body-secondary">' . htmlspecialchars($description) . '</p>';
463  $html .= '<ul class="mb-0"><li class="text-body-secondary">' . implode('</li><li class="text-body-secondary">', $this->passwordPolicyValidator->getRequirements()) . '</li></ul></div>';
464  }
465 
466  break;
467  case 'check':
468  $html = '<input id="field_' . htmlspecialchars($fieldName) . '"
469  type="checkbox"
470  class="form-check-input"
471  name="data' . $dataAdd . '[' . htmlspecialchars($fieldName) . ']"' .
472  ($value ? ' checked="checked"' : '') .
473  $more .
474  ' />';
475  break;
476  case 'language':
477  $html = $this->‪renderLanguageSelect();
478  break;
479  case 'select':
480  if ($config['itemsProcFunc'] ?? false) {
481  $html = GeneralUtility::callUserFunction($config['itemsProcFunc'], $config, $this);
482  } else {
483  $html = '<select id="field_' . htmlspecialchars($fieldName) . '"
484  name="data' . $dataAdd . '[' . htmlspecialchars($fieldName) . ']"' .
485  $more . '>' . LF;
486  foreach ($config['items'] as $key => $optionLabel) {
487  $html .= '<option value="' . htmlspecialchars($key) . '"' . ($value == $key ? ' selected="selected"' : '') . '>' . $this->‪getLabel($optionLabel, '', false) . '</option>' . LF;
488  }
489  $html .= '</select>';
490  }
491  break;
492  case 'user':
493  $html = GeneralUtility::callUserFunction($config['userFunc'], $config, $this);
494  break;
495  case 'button':
496  $label = $this->‪getLabel($config['label'] ?? '');
497  if (!empty($config['clickData'])) {
498  $clickData = $config['clickData'];
499  $buttonAttributes = [
500  'type' => 'button',
501  'class' => 'btn btn-default',
502  'value' => $this->‪getLabel($config['buttonlabel'], '', false),
503  ];
504  if (isset($clickData['eventName'])) {
505  $buttonAttributes['data-event'] = 'click';
506  $buttonAttributes['data-event-name'] = htmlspecialchars($clickData['eventName']);
507  $buttonAttributes['data-event-payload'] = htmlspecialchars($fieldName);
508  }
509  $html = '<input '
510  . GeneralUtility::implodeAttributes($buttonAttributes, false) . ' />';
511  }
512  if (!empty($config['confirm'])) {
513  $confirmData = $config['confirmData'];
514  // cave: values must be processed by `htmlspecialchars()`
515  $buttonAttributes = [
516  'type' => 'button',
517  'class' => 'btn btn-default t3js-modal-trigger',
518  'data-severity' => 'warning',
519  'data-title' => $this->‪getLabel($config['label'], '', false),
520  'data-bs-content' => $this->‪getLabel($confirmData['message'], '', false),
521  'value' => htmlspecialchars($this->‪getLabel($config['buttonlabel'], '', false)),
522  ];
523  if (isset($confirmData['eventName'])) {
524  $buttonAttributes['data-event'] = 'confirm';
525  $buttonAttributes['data-event-name'] = htmlspecialchars($confirmData['eventName']);
526  $buttonAttributes['data-event-payload'] = htmlspecialchars($fieldName);
527  }
528  $html = '<input '
529  . GeneralUtility::implodeAttributes($buttonAttributes, false) . ' />';
530  }
531  break;
532  case 'avatar':
533  // Get current avatar image
534  $html = '';
535  $avatarFileUid = $this->‪getAvatarFileUid((int)$backendUser->user['uid']);
536 
537  if ($avatarFileUid) {
538  $defaultAvatarProvider = GeneralUtility::makeInstance(DefaultAvatarProvider::class);
539  $avatarImage = $defaultAvatarProvider->getImage($backendUser->user, 32);
540  if ($avatarImage) {
541  $icon = '<span class="avatar avatar-size-medium mb-2"><span class="avatar-image">' .
542  '<img alt="" src="' . htmlspecialchars($avatarImage->getUrl()) . '"' .
543  ' width="' . (int)$avatarImage->getWidth() . '"' .
544  ' height="' . (int)$avatarImage->getHeight() . '"' .
545  ' alt="" />' .
546  '</span></span>';
547  $html .= '<span id="image_' . htmlspecialchars($fieldName) . '">' . $icon . ' </span>';
548  }
549  }
550  $html .= '<input id="field_' . htmlspecialchars($fieldName) . '" type="hidden" ' .
551  'name="data' . $dataAdd . '[' . htmlspecialchars($fieldName) . ']"' . $more .
552  ' value="' . $avatarFileUid . '" data-setup-avatar-field="' . htmlspecialchars($fieldName) . '" />';
553 
554  $html .= '<typo3-formengine-container-files><div class="form-group"><div class="form-group"><div class="form-control-wrap">';
555  $html .= '<button type="button" id="add_button_' . htmlspecialchars($fieldName)
556  . '" class="btn btn-default"'
557  . ' title="' . htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:avatar.openFileBrowser')) . '"'
558  . ' data-setup-avatar-url="' . htmlspecialchars((string)$this->uriBuilder->buildUriFromRoute('wizard_element_browser', ['mode' => 'file', 'bparams' => '|||allowed=' . (‪$GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'] ?? '') . '~disallowed=|-0-be_users-avatar-avatar'])) . '"'
559  . '>' . $this->iconFactory->getIcon('actions-insert-record', IconSize::SMALL)
560  . htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:avatar.openFileBrowser'))
561  . '</button>';
562  if ($avatarFileUid) {
563  // Keep space between both buttons with a whitespace (like for other buttons)
564  $html .= ' ';
565  $html .= '<button type="button" id="clear_button_' . htmlspecialchars($fieldName)
566  . '" class="btn btn-default"'
567  . ' title="' . htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:avatar.clear')) . '" '
568  . '>' . $this->iconFactory->getIcon('actions-delete', IconSize::SMALL)
569  . htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:avatar.clear'))
570  . '</button>';
571  }
572  $html .= '</div></div></div></typo3-formengine-container-files>';
573  break;
574  case 'mfa':
575  $label = $this->‪getLabel($config['label'] ?? '');
576  $html = '';
577  $lang = $this->‪getLanguageService();
578  $hasActiveProviders = $this->mfaProviderRegistry->hasActiveProviders($backendUser);
579  if ($hasActiveProviders) {
580  if ($this->mfaProviderRegistry->hasLockedProviders($backendUser)) {
581  $html .= ' <span class="badge badge-danger">' . htmlspecialchars($lang->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:mfaProviders.lockedMfaProviders')) . '</span>';
582  } else {
583  $html .= ' <span class="badge badge-success">' . htmlspecialchars($lang->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:mfaProviders.enabled')) . '</span>';
584  }
585  }
586  $html .= '<div class="formengine-field-item t3js-formengine-field-item">';
587  $html .= '<div class="form-description">' . nl2br(htmlspecialchars($lang->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:mfaProviders.description'))) . '</div>';
588  if (!$this->mfaProviderRegistry->hasProviders()) {
589  $html .= '<span class="badge badge-danger">' . htmlspecialchars($lang->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:mfaProviders.notAvailable')) . '</span>';
590  break;
591  }
592  $html .= '<div class="form-group"><div class="form-group"><div class="form-control-wrap t3js-file-controls">';
593  $html .= '<a href="' . htmlspecialchars((string)$this->uriBuilder->buildUriFromRoute('mfa')) . '" class="btn btn-default">';
594  $html .= htmlspecialchars($lang->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:mfaProviders.' . ($hasActiveProviders ? 'manageLinkTitle' : 'setupLinkTitle')));
595  $html .= '</a>';
596  $html .= '</div></div></div></div>';
597  break;
598  default:
599  $html = '';
600  }
601 
602  $htmlPrepended = '';
603  $htmlAppended = '';
604  if ($type === 'button') {
605  $htmlPrepended = '<div class="formengine-field-item t3js-formengine-field-item"><div class="form-group">'
606  . '<div class="form-group"><div class="form-control-wrap t3js-file-controls">';
607  $htmlAppended = '</div></div></div></div>';
608  }
609  if ($type === 'check') {
610  $htmlPrepended = '<div class="formengine-field-item t3js-formengine-field-item"><div class="form-wizards-wrap">'
611  . '<div class="form-wizards-element"><div class="form-check form-switch">';
612  $htmlAppended = '</div></div></div></div>';
613  }
614  if ($type === 'select' || $type === 'language') {
615  $htmlPrepended = '<div class="formengine-field-item t3js-formengine-field-item"><div class="form-control-wrap">'
616  . '<div class="form-wizards-wrap"><div class="form-wizards-element"><div class="input-group">';
617  $htmlAppended = '</div></div></div></div></div>';
618  }
619  if ($type === 'text' || $type === 'number' || $type === 'email' || $type === 'password') {
620  $htmlPrepended = '<div class="formengine-field-item t3js-formengine-field-item"><div class="form-control-wrap">'
621  . '<div class="form-wizards-wrap"><div class="form-wizards-element">';
622  $htmlAppended = '</div></div></div></div>';
623  }
624 
625  $code[] = '<fieldset class="form-section"><div class="row"><div class="form-group col-md-12">'
626  . $label
627  . $htmlPrepended
628  . $html
629  . $htmlAppended
630  . '</div></div></fieldset>';
631  }
632 
633  $result[] = [
634  'label' => $tabLabel,
635  'content' => count($code) ? implode(LF, $code) : '',
636  ];
637  return $result;
638  }
639 
646  protected function ‪renderLanguageSelect()
647  {
648  $items = $this->locales->getLanguages();
649  $officialLanguages = new ‪OfficialLanguages();
650  $backendUser = $this->‪getBackendUser();
651  $currentSelectedLanguage = (string)($backendUser->user['lang'] ?? 'default');
652  $languageService = $this->‪getLanguageService();
653  $content = '';
654  // get all labels in default language as well
655  $defaultLanguageLabelService = $this->languageServiceFactory->create('default');
656  foreach ($items as $languageCode => $name) {
657  if (!$this->locales->isLanguageKeyAvailable($languageCode)) {
658  continue;
659  }
660  $labelIdentifier = $officialLanguages->getLabelIdentifier($languageCode);
661  $localizedName = htmlspecialchars($languageService->sL($labelIdentifier) ?: $name);
662  $defaultName = $defaultLanguageLabelService->sL($labelIdentifier);
663  if ($defaultName === $localizedName || $defaultName === '') {
664  $defaultName = $languageCode;
665  }
666  if ($defaultName !== $languageCode) {
667  $defaultName .= ' - ' . $languageCode;
668  }
669  $localLabel = ' [' . htmlspecialchars($defaultName) . ']';
670  $content .= '<option value="' . $languageCode . '"' . ($currentSelectedLanguage === $languageCode ? ' selected="selected"' : '') . '>' . $localizedName . $localLabel . '</option>';
671  }
672  $content = '<select id="field_lang" name="data[be_users][lang]" class="form-select">' . $content . '</select>';
673  if ($currentSelectedLanguage !== 'default' && !@is_dir(‪Environment::getLabelsPath() . '/' . $currentSelectedLanguage)) {
674  $languageUnavailableWarning = htmlspecialchars(sprintf($languageService->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:languageUnavailable'), $languageService->sL($officialLanguages->getLabelIdentifier($currentSelectedLanguage)))) . '&nbsp;&nbsp;<br>&nbsp;&nbsp;' . htmlspecialchars($languageService->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:languageUnavailable.' . ($backendUser->isAdmin() ? 'admin' : 'user')));
675  $content = '<br><span class="badge badge-danger">' . $languageUnavailableWarning . '</span><br><br>' . $content;
676  }
677  return $content;
678  }
679 
686  public function ‪renderStartModuleSelect(): string
687  {
688  // Load available backend modules
689  $startModuleSelect = '<option value="">' . htmlspecialchars($this->‪getLanguageService()->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:startModule.firstInMenu')) . '</option>';
690  foreach ($this->moduleProvider->getModules($this->getBackendUser(), false) as ‪$identifier => $module) {
691  if ($module->hasSubModules() || $module->isStandalone()) {
692  $modules = '';
693  if ($module->hasSubModules()) {
694  foreach ($module->getSubModules() as $subModuleIdentifier => $subModule) {
695  $modules .= '<option value="' . htmlspecialchars($subModuleIdentifier) . '"';
696  $modules .= ($this->‪getBackendUser()->uc['startModule'] ?? '') === $subModuleIdentifier ? ' selected="selected"' : '';
697  $modules .= '>' . htmlspecialchars($this->‪getLanguageService()->sL($subModule->getTitle())) . '</option>';
698  }
699  } elseif ($module->isStandalone()) {
700  $modules .= '<option value="' . htmlspecialchars(‪$identifier) . '"';
701  $modules .= ($this->‪getBackendUser()->uc['startModule'] ?? '') === ‪$identifier ? ' selected="selected"' : '';
702  $modules .= '>' . htmlspecialchars($this->‪getLanguageService()->sL($module->getTitle())) . '</option>';
703  }
704  $groupLabel = htmlspecialchars($this->‪getLanguageService()->sL($module->getTitle()));
705  $startModuleSelect .= '<optgroup label="' . htmlspecialchars($groupLabel) . '">' . $modules . '</optgroup>';
706  }
707  }
708  return '<select id="field_startModule" name="data[startModule]" class="form-select">' . $startModuleSelect . '</select>';
709  }
710 
717  protected function ‪checkAccess(array $config)
718  {
719  $access = $config['access'];
720  if (isset(‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['setup']['accessLevelCheck'][$access])) {
721  if (class_exists($access)) {
722  $accessObject = GeneralUtility::makeInstance($access);
723  if (method_exists($accessObject, 'accessLevelCheck')) {
724  // Initialize vars. If method fails, $set will be set to FALSE
725  return $accessObject->accessLevelCheck($config);
726  }
727  }
728  } elseif ($access === 'admin') {
729  return $this->‪getBackendUser()->isAdmin();
730  }
731 
732  return false;
733  }
734 
743  protected function ‪getLabel($str, $key = '', $addLabelTag = true)
744  {
745  $out = htmlspecialchars($this->‪getLanguageService()->sL($str));
746  if (isset($this->overrideConf[$key ?: $str])) {
747  $out = '<span style="color:#999999">' . $out . '</span>';
748  }
749  if ($addLabelTag) {
750  if ($key !== '') {
751  $out = '<label class="form-label t3js-formengine-label" for="field_' . htmlspecialchars($key) . '">' . $out . '</label>';
752  } else {
753  $out = '<label class="form-label t3js-formengine-label">' . $out . '</label>';
754  }
755  }
756  return $out;
757  }
758 
765  protected function ‪getFieldsFromShowItem()
766  {
767  $allowedFields = ‪GeneralUtility::trimExplode(',', ‪$GLOBALS['TYPO3_USER_SETTINGS']['showitem'], true);
768  if ($this->‪getBackendUser()->isAdmin()) {
769  // Do not ask for current password if admin (unknown for other users and no security gain)
770  $key = array_search('passwordCurrent', $allowedFields);
771  if ($key !== false) {
772  unset($allowedFields[$key]);
773  }
774  }
775 
776  $backendUser = $this->‪getBackendUser();
777  if ($backendUser->getOriginalUserIdWhenInSwitchUserMode() && $backendUser->isSystemMaintainer(true)) {
778  // DataHandler denies changing the password of system maintainer users in switch user mode.
779  // Do not show the password fields is this case.
780  $key = array_search('password', $allowedFields);
781  if ($key !== false) {
782  unset($allowedFields[$key]);
783  }
784  $key = array_search('password2', $allowedFields);
785  if ($key !== false) {
786  unset($allowedFields[$key]);
787  }
788  }
789 
790  foreach ($this->tsFieldConf as $fieldName => $userTsFieldConfig) {
791  if (!empty($userTsFieldConfig['disabled'])) {
792  $fieldName = rtrim($fieldName, '.');
793  $key = array_search($fieldName, $allowedFields);
794  if ($key !== false) {
795  unset($allowedFields[$key]);
796  }
797  }
798  }
799  return $allowedFields;
800  }
801 
808  protected function ‪getAvatarFileUid($beUserId)
809  {
810  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_file_reference');
811  $file = $queryBuilder
812  ->select('uid_local')
813  ->from('sys_file_reference')
814  ->where(
815  $queryBuilder->expr()->eq(
816  'tablenames',
817  $queryBuilder->createNamedParameter('be_users')
818  ),
819  $queryBuilder->expr()->eq(
820  'fieldname',
821  $queryBuilder->createNamedParameter('avatar')
822  ),
823  $queryBuilder->expr()->eq(
824  'uid_foreign',
825  $queryBuilder->createNamedParameter($beUserId, ‪Connection::PARAM_INT)
826  )
827  )
828  ->executeQuery()
829  ->fetchOne();
830  return (int)$file;
831  }
832 
839  protected function ‪setAvatarFileUid($beUserId, $fileUid, array &$storeRec)
840  {
841  // Update is only needed when new fileUid is set
842  if ((int)$fileUid === $this->‪getAvatarFileUid($beUserId)) {
843  return;
844  }
845 
846  // If user is not allowed to modify avatar $fileUid is empty - so don't overwrite existing avatar
847  if (empty($fileUid)) {
848  return;
849  }
850 
851  $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_file_reference');
852  $queryBuilder->getRestrictions()->removeAll();
853  $queryBuilder
854  ->delete('sys_file_reference')
855  ->where(
856  $queryBuilder->expr()->eq(
857  'tablenames',
858  $queryBuilder->createNamedParameter('be_users')
859  ),
860  $queryBuilder->expr()->eq(
861  'fieldname',
862  $queryBuilder->createNamedParameter('avatar')
863  ),
864  $queryBuilder->expr()->eq(
865  'uid_foreign',
866  $queryBuilder->createNamedParameter($beUserId, ‪Connection::PARAM_INT)
867  )
868  )
869  ->executeStatement();
870 
871  // If Avatar is marked for delete => set it to empty string so it will be updated properly
872  if ($fileUid === 'delete') {
873  $fileUid = '';
874  }
875 
876  // Create new reference
877  if ((int)$fileUid > 0) {
878  // Get file object
879  try {
880  $file = GeneralUtility::makeInstance(ResourceFactory::class)->getFileObject((int)$fileUid);
881  } catch (‪FileDoesNotExistException $e) {
882  $file = false;
883  }
884 
885  // Check if user is allowed to use the image (only when not in simulation mode)
886  if ($file && !$file->getStorage()->checkFileActionPermission('read', $file)) {
887  $file = false;
888  }
889 
890  // Check if extension is allowed
891  if ($file && $file->isImage()) {
892  // Create new file reference
893  $storeRec['sys_file_reference']['NEW1234'] = [
894  'uid_local' => (int)$fileUid,
895  'uid_foreign' => (int)$beUserId,
896  'tablenames' => 'be_users',
897  'fieldname' => 'avatar',
898  'pid' => 0,
899  ];
900  $storeRec['be_users'][(int)$beUserId]['avatar'] = 'NEW1234';
901  }
902  }
903  }
904 
908  protected function ‪addFlashMessages(‪ModuleTemplate $view): void
909  {
910  $languageService = $this->‪getLanguageService();
911  if ($this->setupIsUpdated && !$this->settingsAreResetToDefault) {
912  $view->‪addFlashMessage($languageService->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:setupWasUpdated'), $languageService->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:UserSettings'));
913  }
914  if ($this->settingsAreResetToDefault) {
915  $view->‪addFlashMessage($languageService->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:settingsAreReset'), $languageService->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:resetConfiguration'));
916  }
917  if ($this->setupIsUpdated || $this->settingsAreResetToDefault) {
918  $view->‪addFlashMessage($languageService->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:activateChanges'), '', ContextualFeedbackSeverity::INFO);
919  }
920  if ($this->passwordIsSubmitted) {
921  switch ($this->passwordIsUpdated) {
923  $view->‪addFlashMessage($languageService->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:oldPassword_failed'), $languageService->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:newPassword'), ContextualFeedbackSeverity::ERROR);
924  break;
926  $view->‪addFlashMessage($languageService->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:newPassword_failed'), $languageService->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:newPassword'), ContextualFeedbackSeverity::ERROR);
927  break;
929  $view->‪addFlashMessage($languageService->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:newPassword_ok'), $languageService->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:newPassword'));
930  break;
932  $view->‪addFlashMessage($languageService->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:passwordPolicyFailed'), $languageService->sL('LLL:EXT:setup/Resources/Private/Language/locallang.xlf:newPassword'), ContextualFeedbackSeverity::ERROR);
933  break;
934  }
935  }
936  }
937 
939  {
940  return ‪$GLOBALS['BE_USER'];
941  }
942 
944  {
945  return ‪$GLOBALS['LANG'];
946  }
947 }
‪TYPO3\CMS\Core\Localization\LanguageServiceFactory
Definition: LanguageServiceFactory.php:25
‪TYPO3\CMS\Core\DataHandling\DataHandler
Definition: DataHandler.php:94
‪TYPO3\CMS\Setup\Controller\SetupModuleController\getFieldsFromShowItem
‪string[] getFieldsFromShowItem()
Definition: SetupModuleController.php:765
‪TYPO3\CMS\Core\Crypto\PasswordHashing\PasswordHashFactory
Definition: PasswordHashFactory.php:27
‪TYPO3\CMS\Core\Database\Connection\PARAM_INT
‪const PARAM_INT
Definition: Connection.php:52
‪TYPO3\CMS\Setup\Controller\SetupModuleController\PASSWORD_OLD_WRONG
‪const PASSWORD_OLD_WRONG
Definition: SetupModuleController.php:70
‪TYPO3\CMS\Setup\Controller\SetupModuleController\getButtons
‪getButtons(ModuleTemplate $view)
Definition: SetupModuleController.php:337
‪TYPO3\CMS\Backend\Template\ModuleTemplateFactory
Definition: ModuleTemplateFactory.php:33
‪TYPO3\CMS\Setup\Controller\SetupModuleController\$overrideConf
‪array $overrideConf
Definition: SetupModuleController.php:73
‪TYPO3\CMS\Setup\Controller\SetupModuleController
Definition: SetupModuleController.php:66
‪TYPO3\CMS\Core\Crypto\PasswordHashing\InvalidPasswordHashException
Definition: InvalidPasswordHashException.php:25
‪TYPO3\CMS\Setup\Controller\SetupModuleController\$passwordIsUpdated
‪int $passwordIsUpdated
Definition: SetupModuleController.php:77
‪TYPO3\CMS\Core\Core\Environment\getLabelsPath
‪static getLabelsPath()
Definition: Environment.php:233
‪TYPO3\CMS\Setup\Controller\SetupModuleController\$languageUpdate
‪bool $languageUpdate
Definition: SetupModuleController.php:74
‪TYPO3\CMS\Setup\Controller\SetupModuleController\storeIncomingData
‪storeIncomingData(ServerRequestInterface $request)
Definition: SetupModuleController.php:173
‪TYPO3\CMS\Setup\Controller\SetupModuleController\PASSWORD_UPDATED
‪const PASSWORD_UPDATED
Definition: SetupModuleController.php:68
‪TYPO3\CMS\Backend\Template\ModuleTemplate\addFlashMessage
‪addFlashMessage(string $messageBody, string $messageTitle='', ContextualFeedbackSeverity $severity=ContextualFeedbackSeverity::OK, bool $storeInSession=true)
Definition: ModuleTemplate.php:229
‪TYPO3\CMS\Backend\Backend\Avatar\DefaultAvatarProvider
Definition: DefaultAvatarProvider.php:30
‪TYPO3\CMS\Core\Localization\Locales
Definition: Locales.php:36
‪TYPO3\CMS\Setup\Controller\SetupModuleController\getLanguageService
‪getLanguageService()
Definition: SetupModuleController.php:943
‪TYPO3\CMS\Core\Resource\Exception\FileDoesNotExistException
Definition: FileDoesNotExistException.php:21
‪TYPO3\CMS\Core\Imaging\IconFactory
Definition: IconFactory.php:34
‪TYPO3\CMS\Setup\Controller\SetupModuleController\PASSWORD_POLICY_FAILED
‪const PASSWORD_POLICY_FAILED
Definition: SetupModuleController.php:71
‪TYPO3\CMS\Setup\Controller\SetupModuleController\processAdditionalJavaScriptModules
‪processAdditionalJavaScriptModules()
Definition: SetupModuleController.php:161
‪TYPO3\CMS\Setup\Controller\SetupModuleController\$setupIsUpdated
‪bool $setupIsUpdated
Definition: SetupModuleController.php:79
‪TYPO3\CMS\Backend\Module\ModuleProvider
Definition: ModuleProvider.php:29
‪TYPO3\CMS\Setup\Controller\SetupModuleController\renderLanguageSelect
‪string renderLanguageSelect()
Definition: SetupModuleController.php:646
‪TYPO3\CMS\Setup\Controller\SetupModuleController\getLabel
‪string getLabel($str, $key='', $addLabelTag=true)
Definition: SetupModuleController.php:743
‪TYPO3\CMS\Backend\Template\ModuleTemplate
Definition: ModuleTemplate.php:46
‪TYPO3\CMS\Core\Type\ContextualFeedbackSeverity
‪ContextualFeedbackSeverity
Definition: ContextualFeedbackSeverity.php:25
‪TYPO3\CMS\Setup\Controller\SetupModuleController\PASSWORD_NOT_UPDATED
‪const PASSWORD_NOT_UPDATED
Definition: SetupModuleController.php:67
‪TYPO3\CMS\Core\Page\PageRenderer
Definition: PageRenderer.php:44
‪TYPO3\CMS\Core\SysLog\Action\Setting
Definition: Setting.php:24
‪TYPO3\CMS\Setup\Controller\SetupModuleController\$passwordIsSubmitted
‪bool $passwordIsSubmitted
Definition: SetupModuleController.php:78
‪TYPO3\CMS\Backend\Routing\UriBuilder
Definition: UriBuilder.php:44
‪TYPO3\CMS\Setup\Controller\SetupModuleController\addFlashMessages
‪addFlashMessages(ModuleTemplate $view)
Definition: SetupModuleController.php:908
‪TYPO3\CMS\Core\PasswordPolicy\PasswordPolicyValidator
Definition: PasswordPolicyValidator.php:27
‪TYPO3\CMS\Core\Resource\ResourceFactory
Definition: ResourceFactory.php:42
‪TYPO3\CMS\Core\SysLog\Error
Definition: Error.php:24
‪TYPO3\CMS\Core\Authentication\BackendUserAuthentication
Definition: BackendUserAuthentication.php:62
‪TYPO3\CMS\Setup\Controller\SetupModuleController\renderUserSetup
‪array renderUserSetup()
Definition: SetupModuleController.php:362
‪TYPO3\CMS\Setup\Controller\SetupModuleController\initialize
‪initialize(ServerRequestInterface $request)
Definition: SetupModuleController.php:135
‪TYPO3\CMS\Core\Database\Connection
Definition: Connection.php:41
‪TYPO3\CMS\Backend\Template\ModuleTemplate\getDocHeaderComponent
‪getDocHeaderComponent()
Definition: ModuleTemplate.php:181
‪TYPO3\CMS\Setup\Controller\SetupModuleController\$settingsAreResetToDefault
‪bool $settingsAreResetToDefault
Definition: SetupModuleController.php:80
‪TYPO3\CMS\Core\FormProtection\FormProtectionFactory
Definition: FormProtectionFactory.php:43
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:25
‪TYPO3\CMS\Core\PasswordPolicy\Event\EnrichPasswordValidationContextDataEvent
Definition: EnrichPasswordValidationContextDataEvent.php:30
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:41
‪TYPO3\CMS\Setup\Controller\SetupModuleController\PASSWORD_NOT_THE_SAME
‪const PASSWORD_NOT_THE_SAME
Definition: SetupModuleController.php:69
‪TYPO3\CMS\Setup\Controller\SetupModuleController\mainAction
‪mainAction(ServerRequestInterface $request)
Definition: SetupModuleController.php:113
‪TYPO3\CMS\Setup\Controller\SetupModuleController\$passwordPolicyValidator
‪PasswordPolicyValidator $passwordPolicyValidator
Definition: SetupModuleController.php:82
‪TYPO3\CMS\Backend\Attribute\AsController
Definition: AsController.php:25
‪TYPO3\CMS\Setup\Controller\SetupModuleController\renderStartModuleSelect
‪string renderStartModuleSelect()
Definition: SetupModuleController.php:686
‪TYPO3\CMS\Core\PasswordPolicy\PasswordPolicyAction
‪PasswordPolicyAction
Definition: PasswordPolicyAction.php:24
‪TYPO3\CMS\Core\Localization\LanguageService
Definition: LanguageService.php:46
‪TYPO3\CMS\Core\Localization\OfficialLanguages
Definition: OfficialLanguages.php:26
‪TYPO3\CMS\Core\Database\ConnectionPool
Definition: ConnectionPool.php:46
‪TYPO3\CMS\Setup\Controller\SetupModuleController\$pagetreeNeedsRefresh
‪bool $pagetreeNeedsRefresh
Definition: SetupModuleController.php:75
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:52
‪TYPO3\CMS\Setup\Controller
Definition: SetupModuleController.php:18
‪TYPO3\CMS\Setup\Controller\SetupModuleController\setAvatarFileUid
‪setAvatarFileUid($beUserId, $fileUid, array &$storeRec)
Definition: SetupModuleController.php:839
‪TYPO3\CMS\Setup\Controller\SetupModuleController\__construct
‪__construct(protected readonly EventDispatcherInterface $eventDispatcher, protected readonly MfaProviderRegistry $mfaProviderRegistry, protected readonly IconFactory $iconFactory, protected readonly PageRenderer $pageRenderer, protected readonly ModuleTemplateFactory $moduleTemplateFactory, protected readonly LanguageServiceFactory $languageServiceFactory, protected readonly ModuleProvider $moduleProvider, protected readonly UriBuilder $uriBuilder, protected readonly FormProtectionFactory $formProtectionFactory, protected readonly Locales $locales,)
Definition: SetupModuleController.php:84
‪TYPO3\CMS\Setup\Controller\SetupModuleController\$tsFieldConf
‪array $tsFieldConf
Definition: SetupModuleController.php:76
‪TYPO3\CMS\Core\Utility\GeneralUtility\trimExplode
‪static list< string > trimExplode(string $delim, string $string, bool $removeEmptyValues=false, int $limit=0)
Definition: GeneralUtility.php:822
‪TYPO3\CMS\Setup\Controller\SetupModuleController\checkAccess
‪bool checkAccess(array $config)
Definition: SetupModuleController.php:717
‪TYPO3\CMS\Setup\Controller\SetupModuleController\getAvatarFileUid
‪int getAvatarFileUid($beUserId)
Definition: SetupModuleController.php:808
‪TYPO3\CMS\Webhooks\Message\$identifier
‪identifier readonly string $identifier
Definition: FileAddedMessage.php:37
‪TYPO3\CMS\Core\SysLog\Type
Definition: Type.php:28
‪TYPO3\CMS\Setup\Event\AddJavaScriptModulesEvent
Definition: AddJavaScriptModulesEvent.php:24
‪TYPO3\CMS\Setup\Controller\SetupModuleController\getBackendUser
‪getBackendUser()
Definition: SetupModuleController.php:938
‪TYPO3\CMS\Core\Authentication\Mfa\MfaProviderRegistry
Definition: MfaProviderRegistry.php:28
‪TYPO3\CMS\Core\PasswordPolicy\Validator\Dto\ContextData
Definition: ContextData.php:28