From ecbce5ac045896510c222cbc3a24f72bc673bed8 Mon Sep 17 00:00:00 2001
From: Fabien Udriot <fabien.udriot@ecodev.ch>
Date: Wed, 2 Oct 2013 17:49:26 +0200
Subject: [PATCH] [FEATURE] Control visibility of modules in the BE
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Currently there is no way for controlling the visibility
of a module in the BE. The patch introduces User TSconfig
which can be used to hide modules from the main menu.

options.hideModules = file, help

options.hideModules.web := addToList(func,info)

options.hideModules.system = BelogLog

The change only influences the visibility of modules in the menu
and does not control the access (permission) which still must be
done in the ACL of a BE User / Group as usually.

Change-Id: I6c2ec2c389a154440932afa16f9ca3a2cb4b8116
Releases: 6.2
Resolves: #52482
Documentation: #52692
Reviewed-on: https://review.typo3.org/24274
Reviewed-by: Steffen Müller
Tested-by: Steffen Müller
Reviewed-by: Christian Kuhn
Tested-by: Christian Kuhn
Reviewed-by: Anja Leichsenring
Tested-by: Anja Leichsenring
---
 .../backend/Classes/View/ModuleMenuView.php   | 31 ++++++
 .../Tests/Unit/View/ModuleMenuViewTest.php    | 96 +++++++++++++++++++
 2 files changed, 127 insertions(+)
 create mode 100644 typo3/sysext/backend/Tests/Unit/View/ModuleMenuViewTest.php

diff --git a/typo3/sysext/backend/Classes/View/ModuleMenuView.php b/typo3/sysext/backend/Classes/View/ModuleMenuView.php
index d7c590d498ab..c56e392fa571 100644
--- a/typo3/sysext/backend/Classes/View/ModuleMenuView.php
+++ b/typo3/sysext/backend/Classes/View/ModuleMenuView.php
@@ -165,6 +165,33 @@ class ModuleMenuView {
 		$GLOBALS['BE_USER']->writeUC();
 	}
 
+	/**
+	 * Reads User configuration from options.hideModules and removes
+	 * modules from $this->loadedModules accordingly.
+	 *
+	 * @return void
+	 */
+	protected function unsetHiddenModules() {
+		// Hide modules if set in userTS.
+		$hiddenModules = $GLOBALS['BE_USER']->getTSConfig('options.hideModules');
+		if (!empty($hiddenModules['value'])) {
+			$hiddenMainModules = GeneralUtility::trimExplode(',', $hiddenModules['value'], TRUE);
+			foreach ($hiddenMainModules as $hiddenMainModule) {
+				unset($this->loadedModules[$hiddenMainModule]);
+			}
+		}
+
+		// Hide sub-modules if set in userTS.
+		if (!empty($hiddenModules['properties']) && is_array($hiddenModules['properties'])) {
+			foreach ($hiddenModules['properties'] as $mainModuleName => $subModules) {
+				$hiddenSubModules = GeneralUtility::trimExplode(',', $subModules, TRUE);
+				foreach ($hiddenSubModules as $hiddenSubModule) {
+					unset($this->loadedModules[$mainModuleName]['sub'][$hiddenSubModule]);
+				}
+			}
+		}
+	}
+
 	/**
 	 * gets the raw module data
 	 *
@@ -176,6 +203,10 @@ class ModuleMenuView {
 		if ($GLOBALS['BE_USER']->getTSConfigVal('options.disableDocModuleInAB')) {
 			unset($this->loadedModules['doc']);
 		}
+
+		// Unset modules that are meant to be hidden from the menu.
+		$this->unsetHiddenModules();
+
 		foreach ($this->loadedModules as $moduleName => $moduleData) {
 			$moduleLink = '';
 			if (!is_array($moduleData['sub'])) {
diff --git a/typo3/sysext/backend/Tests/Unit/View/ModuleMenuViewTest.php b/typo3/sysext/backend/Tests/Unit/View/ModuleMenuViewTest.php
new file mode 100644
index 000000000000..8a151aea775b
--- /dev/null
+++ b/typo3/sysext/backend/Tests/Unit/View/ModuleMenuViewTest.php
@@ -0,0 +1,96 @@
+<?php
+namespace TYPO3\CMS\Backend\Tests\Unit\View;
+
+/***************************************************************
+ *  Copyright notice
+ *
+ *  (c) 2013 Fabien Udriot <fabien.udriot@typo3.org>
+ *  All rights reserved
+ *
+ *  This script is part of the TYPO3 project. The TYPO3 project is
+ *  free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  The GNU General Public License can be found at
+ *  http://www.gnu.org/copyleft/gpl.html.
+ *  A copy is found in the textfile GPL.txt and important notices to the license
+ *  from the author is found in LICENSE.txt distributed with these scripts.
+ *
+ *
+ *  This script is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  This copyright notice MUST APPEAR in all copies of the script!
+ ***************************************************************/
+
+/**
+ * Test for TYPO3\CMS\Backend\ModuleMenuView
+ */
+class ModuleMenuViewTest extends \TYPO3\CMS\Core\Tests\UnitTestCase {
+
+	/**
+	 * @test
+	 */
+	public function unsetHiddenModulesUnsetsHiddenModules() {
+		/** @var \TYPO3\CMS\Backend\View\ModuleMenuView|\PHPUnit_Framework_MockObject_MockObject|\TYPO3\CMS\Core\Tests\AccessibleObjectInterface $moduleMenuViewMock */
+		$moduleMenuViewMock = $this->getAccessibleMock(
+			'TYPO3\\CMS\\Backend\\View\\ModuleMenuView',
+			array('dummy'),
+			array(),
+			'',
+			FALSE
+		);
+
+		$loadedModulesFixture = array(
+			'file' => array(),
+			'tools' => array(),
+			'web' => array(
+				'sub' => array(
+					'list' => array(),
+					'func' => array(),
+					'info' => array(),
+				),
+			),
+			'user' => array(
+				'sub' => array(
+					'task' => array(),
+					'settings' => array(),
+				),
+			),
+		);
+		$moduleMenuViewMock->_set('loadedModules', $loadedModulesFixture);
+
+		$userTsFixture = array(
+			'value' => 'file,help',
+			'properties' => array(
+				'web' => 'list,func',
+				'user' => 'task',
+			),
+		);
+
+		$GLOBALS['BE_USER'] = $this->getMock('TYPO3\\CMS\\Core\\Authentication\\BackendUserAuthentication', array(), array(), '', FALSE);
+		$GLOBALS['BE_USER']->expects($this->any())->method('getTSConfig')->will($this->returnValue($userTsFixture));
+
+		$expectedResult = array(
+			'tools' => array(),
+			'web' => array(
+				'sub' => array(
+					'info' => array(),
+				),
+			),
+			'user' => array(
+				'sub' => array(
+					'settings' => array(),
+				),
+			),
+		);
+
+		$moduleMenuViewMock->_call('unsetHiddenModules');
+		$actualResult = $moduleMenuViewMock->_get('loadedModules');
+		$this->assertSame($expectedResult, $actualResult);
+	}
+}
\ No newline at end of file
-- 
GitLab