diff --git a/typo3/sysext/backend/Classes/Backend/ToolbarItems/UserToolbarItem.php b/typo3/sysext/backend/Classes/Backend/ToolbarItems/UserToolbarItem.php index 4783beb300e95f17b5eb8b4a6198533e9032c497..0a4c44fb580b558924a06be811ffb80d72b3e1ba 100644 --- a/typo3/sysext/backend/Classes/Backend/ToolbarItems/UserToolbarItem.php +++ b/typo3/sysext/backend/Classes/Backend/ToolbarItems/UserToolbarItem.php @@ -17,6 +17,7 @@ namespace TYPO3\CMS\Backend\Backend\ToolbarItems; use TYPO3\CMS\Backend\Domain\Repository\Module\BackendModuleRepository; use TYPO3\CMS\Backend\Toolbar\ToolbarItemInterface; use TYPO3\CMS\Backend\Utility\BackendUtility; +use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Fluid\View\StandaloneView; @@ -58,13 +59,36 @@ class UserToolbarItem implements ToolbarItemInterface */ public function getDropDown() { + $backendUser = $this->getBackendUser(); + /** @var BackendModuleRepository $backendModuleRepository */ $backendModuleRepository = GeneralUtility::makeInstance(BackendModuleRepository::class); + + $mostRecentUsers = []; + if (ExtensionManagementUtility::isLoaded('beuser') + && $backendUser->isAdmin() + && (int)$backendUser->user['ses_backuserid'] === 0 + && isset($backendUser->uc['recentSwitchedToUsers']) + && is_array($backendUser->uc['recentSwitchedToUsers']) + ) { + foreach ($backendUser->uc['recentSwitchedToUsers'] as $userUid) { + $backendUserRecord = BackendUtility::getRecord('be_users', $userUid); + $backendUserRecord['switchUserLink'] = BackendUtility::getModuleUrl( + 'system_BeuserTxBeuser', + [ + 'SwitchUser' => $backendUserRecord['uid'] + ] + ); + $mostRecentUsers[] = $backendUserRecord; + } + } + $view = $this->getFluidTemplateObject('UserToolbarItemDropDown.html'); $view->assignMultiple([ 'modules' => $backendModuleRepository->findByModuleName('user')->getChildren(), 'logoutUrl' => BackendUtility::getModuleUrl('logout'), 'switchUserMode' => $this->getBackendUser()->user['ses_backuserid'], + 'recentUsers' => $mostRecentUsers, ]); return $view->render(); } diff --git a/typo3/sysext/backend/Resources/Private/Language/locallang.xlf b/typo3/sysext/backend/Resources/Private/Language/locallang.xlf index 5387089f5e1b677e75ed065591a43110600a0af9..98dc8f1aee312f452e02a51e6180955fffd4ab11 100644 --- a/typo3/sysext/backend/Resources/Private/Language/locallang.xlf +++ b/typo3/sysext/backend/Resources/Private/Language/locallang.xlf @@ -19,6 +19,12 @@ <source>Your system is fully operational. Have a nice day.</source> </trans-unit> + <trans-unit id="usermodule.su.list"> + <source>Recently 'switched to' users</source> + </trans-unit> + <trans-unit id="usermodule.su.tooltip"> + <source>Switch to user %s</source> + </trans-unit> <trans-unit id="config.loginLogo"> <source>Logo: If set, this logo will be used instead of the TYPO3 logo above the login credential fields (e.g. fileadmin/images/login-logo.png or EXT:my_theme/Resources/Public/Images/login-logo.png or //domain.tld/login-logo.png)</source> </trans-unit> diff --git a/typo3/sysext/backend/Resources/Private/Templates/ToolbarItems/UserToolbarItemDropDown.html b/typo3/sysext/backend/Resources/Private/Templates/ToolbarItems/UserToolbarItemDropDown.html index 475be8c2b1d59336a5972897901d9ee74ad1d0eb..c7e28c39b27d23651ccd00b40851435a87538baa 100644 --- a/typo3/sysext/backend/Resources/Private/Templates/ToolbarItems/UserToolbarItemDropDown.html +++ b/typo3/sysext/backend/Resources/Private/Templates/ToolbarItems/UserToolbarItemDropDown.html @@ -1,4 +1,4 @@ -<html xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers" data-namespace-typo3-fluid="true"> +<html xmlns:core="http://typo3.org/ns/TYPO3/CMS/Core/ViewHelpers" xmlns:be="http://typo3.org/ns/TYPO3/CMS/Backend/ViewHelpers" data-namespace-typo3-fluid="true"> <h3 class="dropdown-headline"> {f:translate(key: 'LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:labels.user')} </h3> @@ -24,6 +24,31 @@ </div> <hr> </f:if> +<f:if condition="{f:count(subject: recentUsers)} > 0"> + <h3 class="dropdown-headline"><f:translate key="usermodule.su.list" /></h3> + <div class="dropdown-table"> + <f:for each="{recentUsers}" as="user"> + <div class="dropdown-table-row"> + <div class="dropdown-table-column dropdown-table-icon"> + <be:avatar backendUser="{user.uid}" size="32" /> + </div> + <div class="dropdown-table-column dropdown-table-title"> + <a href="{user.switchUserLink}" title="{f:translate(key: 'usermodule.su.tooltip', arguments: {0: user.username})}"> + <f:if condition="{user.realName}"> + <f:then> + {user.realName} + </f:then> + <f:else> + {user.username} + </f:else> + </f:if> + </a> + </div> + </div> + </f:for> + </div> + <hr> +</f:if> <a href="{logoutUrl}" class="btn btn-danger pull-left" target="_top"> <core:icon identifier="actions-logout" size="small" alternativeMarkupIdentifier="inline"/> <f:if condition="{switchUserMode}"> @@ -35,4 +60,4 @@ </f:else> </f:if> </a> -</html> +</html> \ No newline at end of file diff --git a/typo3/sysext/beuser/Classes/Controller/BackendUserController.php b/typo3/sysext/beuser/Classes/Controller/BackendUserController.php index 56c1793d8e5c110324ef52c60f1c48bfba17bb3a..1a6a4fd0f8a96ff47bdad0f7c2e320262beb21bf 100644 --- a/typo3/sysext/beuser/Classes/Controller/BackendUserController.php +++ b/typo3/sysext/beuser/Classes/Controller/BackendUserController.php @@ -27,6 +27,11 @@ use TYPO3\CMS\Lang\LanguageService; */ class BackendUserController extends BackendUserActionController { + /** + * @var int + */ + const RECENT_USERS_LIMIT = 3; + /** * @var \TYPO3\CMS\Beuser\Domain\Model\ModuleData */ @@ -243,6 +248,7 @@ class BackendUserController extends BackendUserActionController if (is_array($targetUser) && $this->getBackendUserAuthentication()->isAdmin()) { // Set backend user listing module as starting module for switchback $this->getBackendUserAuthentication()->uc['startModuleOnFirstLogin'] = 'system_BeuserTxBeuser'; + $this->getBackendUserAuthentication()->uc['recentSwitchedToUsers'] = $this->generateListOfMostRecentSwitchedUsers($targetUser['uid']); $this->getBackendUserAuthentication()->writeUC(); $sessionBackend = $this->getSessionBackend(); @@ -259,6 +265,33 @@ class BackendUserController extends BackendUserActionController } } + /** + * Generates a list of users to whom where switched in the past. This is limited by RECENT_USERS_LIMIT. + * + * @param int $targetUserUid + * @return int[] + */ + protected function generateListOfMostRecentSwitchedUsers(int $targetUserUid): array + { + $latestUserUids = []; + $backendUser = $this->getBackendUserAuthentication(); + + if (isset($backendUser->uc['recentSwitchedToUsers']) && is_array($backendUser->uc['recentSwitchedToUsers'])) { + $latestUserUids = $backendUser->uc['recentSwitchedToUsers']; + } + + // Remove potentially existing user in that list + $index = array_search($targetUserUid, $latestUserUids, true); + if ($index !== false) { + unset($latestUserUids[$index]); + } + + array_unshift($latestUserUids, $targetUserUid); + $latestUserUids = array_slice($latestUserUids, 0, static::RECENT_USERS_LIMIT); + + return $latestUserUids; + } + /** * @return BackendUserAuthentication */ diff --git a/typo3/sysext/beuser/Tests/Unit/Controller/BackendUserControllerTest.php b/typo3/sysext/beuser/Tests/Unit/Controller/BackendUserControllerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..aa62f8c42fa8e064d703ef2758ce0b9f5e2d1f51 --- /dev/null +++ b/typo3/sysext/beuser/Tests/Unit/Controller/BackendUserControllerTest.php @@ -0,0 +1,66 @@ +<?php +declare(strict_types=1); +namespace TYPO3\CMS\Beuser\Tests\Unit\Controller; + +/* + * This file is part of the TYPO3 CMS project. + * + * It is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License, either version 2 + * of the License, or any later version. + * + * For the full copyright and license information, please read the + * LICENSE.txt file that was distributed with this source code. + * + * The TYPO3 project - inspiring people to share! + */ + +use TYPO3\CMS\Beuser\Controller\BackendUserController; +use TYPO3\CMS\Core\Authentication\BackendUserAuthentication; + +/** + * Test case + */ +class BackendUserControllerTest extends \TYPO3\TestingFramework\Core\Unit\UnitTestCase +{ + /** + * @var BackendUserController|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\TestingFramework\Core\AccessibleObjectInterface + */ + protected $subject; + + protected function setUp() + { + $GLOBALS['BE_USER'] = $this->createMock(BackendUserAuthentication::class); + $GLOBALS['BE_USER']->uc = [ + 'recentSwitchedToUsers' => [] + ]; + + $this->subject = $this->getAccessibleMock(BackendUserController::class, ['dummy'], [], '', false); + } + + /** + * @test + */ + public function generateListOfLatestSwitchedUsersReturnsCorrectAmountAndOrder() + { + $items = range(1, BackendUserController::RECENT_USERS_LIMIT + 5); + $expected = array_reverse(array_slice($items, -BackendUserController::RECENT_USERS_LIMIT)); + foreach ($items as $id) { + $GLOBALS['BE_USER']->uc['recentSwitchedToUsers'] = $this->subject->_call('generateListOfMostRecentSwitchedUsers', $id); + } + + static::assertCount(BackendUserController::RECENT_USERS_LIMIT, $GLOBALS['BE_USER']->uc['recentSwitchedToUsers']); + static::assertSame($expected, $GLOBALS['BE_USER']->uc['recentSwitchedToUsers']); + } + + /** + * @test + */ + public function listOfLatestSwitchedUsersDoesNotContainTheSameUserTwice() + { + $GLOBALS['BE_USER']->uc['recentSwitchedToUsers'] = $this->subject->_call('generateListOfMostRecentSwitchedUsers', 100); + $GLOBALS['BE_USER']->uc['recentSwitchedToUsers'] = $this->subject->_call('generateListOfMostRecentSwitchedUsers', 100); + + static::assertCount(1, $GLOBALS['BE_USER']->uc['recentSwitchedToUsers']); + } +} diff --git a/typo3/sysext/core/Documentation/Changelog/master/Feature-80581-RenderListOfRecentlyUsersThatWereSwitchedTo.rst b/typo3/sysext/core/Documentation/Changelog/master/Feature-80581-RenderListOfRecentlyUsersThatWereSwitchedTo.rst new file mode 100644 index 0000000000000000000000000000000000000000..101296ebe08d2d1d333a6dc8d751dd40ce117d7b --- /dev/null +++ b/typo3/sysext/core/Documentation/Changelog/master/Feature-80581-RenderListOfRecentlyUsersThatWereSwitchedTo.rst @@ -0,0 +1,21 @@ +.. include:: ../../Includes.txt + +===================================================================== +Feature: #80581 - Render list of recently users that were switched to +===================================================================== + +See :issue:`80581` + +Description +=========== + +When a backend user with admin privileges switches to another user, the entered user is now stored in the uc. The users +stored in this list will be rendered into the user menu to allow quick switching to the recent users. + + +Impact +====== + +The user menu renders up to three users to which the currently logged in admin switched to. + +.. index:: Backend \ No newline at end of file