diff options
-rw-r--r-- | apps/files/appinfo/app.php | 14 | ||||
-rw-r--r-- | apps/files/appinfo/info.xml | 7 | ||||
-rw-r--r-- | apps/files/img/app.svg | 6 | ||||
-rw-r--r-- | lib/private/NavigationManager.php | 107 | ||||
-rw-r--r-- | lib/private/Server.php | 8 | ||||
-rw-r--r-- | tests/lib/NavigationManagerTest.php | 66 |
6 files changed, 188 insertions, 20 deletions
diff --git a/apps/files/appinfo/app.php b/apps/files/appinfo/app.php index a194bb5e795..63acda3a706 100644 --- a/apps/files/appinfo/app.php +++ b/apps/files/appinfo/app.php @@ -26,20 +26,10 @@ * along with this program. If not, see <http://www.gnu.org/licenses/> * */ +// required for translation purpose +// t('Files') $l = \OC::$server->getL10N('files'); -\OC::$server->getNavigationManager()->add(function () { - $urlGenerator = \OC::$server->getURLGenerator(); - $l = \OC::$server->getL10N('files'); - return [ - 'id' => 'files_index', - 'order' => 0, - 'href' => $urlGenerator->linkToRoute('files.view.index'), - 'icon' => $urlGenerator->imagePath('core', 'places/files.svg'), - 'name' => $l->t('Files'), - ]; -}); - \OC::$server->getSearch()->registerProvider('OC\Search\Provider\File', array('apps' => array('files'))); $templateManager = \OC_Helper::getFileTemplateManager(); diff --git a/apps/files/appinfo/info.xml b/apps/files/appinfo/info.xml index a25c043f332..2bb4d98c158 100644 --- a/apps/files/appinfo/info.xml +++ b/apps/files/appinfo/info.xml @@ -53,4 +53,11 @@ <command>OCA\Files\Command\DeleteOrphanedFiles</command> <command>OCA\Files\Command\TransferOwnership</command> </commands> + + <navigation> + <name>Files</name> + <route>files.view.index</route> + <order>0</order> + </navigation> + </info> diff --git a/apps/files/img/app.svg b/apps/files/img/app.svg new file mode 100644 index 00000000000..130f59eab23 --- /dev/null +++ b/apps/files/img/app.svg @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg xmlns="http://www.w3.org/2000/svg" height="32" width="32" version="1.1" viewBox="0 0 32 32"> + <g fill-rule="evenodd" transform="matrix(1.7333 0 0 1.7333 -344.09 -1727.8)" fill="#fff"> + <path d="m200.2 999.72c-0.28913 0-0.53125 0.2421-0.53125 0.5312v12.784c0 0.2985 0.23264 0.5312 0.53125 0.5312h15.091c0.2986 0 0.53124-0.2327 0.53124-0.5312l0.0004-10.474c0-0.2889-0.24211-0.5338-0.53124-0.5338l-7.5457 0.0005-2.3076-2.3078z" fill-rule="evenodd" fill="#fff"/> + </g> +</svg> diff --git a/lib/private/NavigationManager.php b/lib/private/NavigationManager.php index 3e9ddfc6466..f7bc02943a3 100644 --- a/lib/private/NavigationManager.php +++ b/lib/private/NavigationManager.php @@ -1,6 +1,6 @@ <?php /** - * @copyright Copyright (c) 2016, ownCloud, Inc. + * @copyright Copyright (c) 2016, ownCloud GmbH * * @author Bart Visscher <bartv@thisnet.nl> * @author Joas Schilling <coding@schilljs.com> @@ -26,13 +26,46 @@ namespace OC; +use OC\App\AppManager; +use OCP\App\IAppManager; +use OCP\IGroupManager; +use OCP\INavigationManager; +use OCP\IURLGenerator; +use OCP\IUserSession; +use OCP\L10N\IFactory; + /** * Manages the ownCloud navigation */ -class NavigationManager implements \OCP\INavigationManager { - protected $entries = array(); - protected $closureEntries = array(); + +class NavigationManager implements INavigationManager { + protected $entries = []; + protected $closureEntries = []; protected $activeEntry; + /** @var bool */ + protected $init = false; + /** @var IAppManager|AppManager */ + protected $appManager; + /** @var IURLGenerator */ + private $urlGenerator; + /** @var IFactory */ + private $l10nFac; + /** @var IUserSession */ + private $userSession; + /** @var IGroupManager */ + private $groupManager; + + public function __construct(IAppManager $appManager = null, + IURLGenerator $urlGenerator = null, + IFactory $l10nFac = null, + IUserSession $userSession = null, + IGroupManager$groupManager = null) { + $this->appManager = $appManager; + $this->urlGenerator = $urlGenerator; + $this->l10nFac = $l10nFac; + $this->userSession = $userSession; + $this->groupManager = $groupManager; + } /** * Creates a new navigation entry @@ -60,6 +93,7 @@ class NavigationManager implements \OCP\INavigationManager { * @return array an array of the added entries */ public function getAll() { + $this->init(); foreach ($this->closureEntries as $c) { $this->add($c()); } @@ -71,8 +105,9 @@ class NavigationManager implements \OCP\INavigationManager { * removes all the entries */ public function clear() { - $this->entries = array(); - $this->closureEntries = array(); + $this->entries = []; + $this->closureEntries = []; + $this->init = false; } /** @@ -93,4 +128,64 @@ class NavigationManager implements \OCP\INavigationManager { public function getActiveEntry() { return $this->activeEntry; } + + private function init() { + if ($this->init) { + return; + } + $this->init = true; + if (is_null($this->appManager)) { + return; + } + foreach ($this->appManager->getInstalledApps() as $app) { + // load plugins and collections from info.xml + $info = $this->appManager->getAppInfo($app); + if (!isset($info['navigation'])) { + continue; + } + $nav = $info['navigation']; + if (!isset($nav['name'])) { + continue; + } + if (!isset($nav['route'])) { + continue; + } + $role = isset($nav['@attributes']['role']) ? $nav['@attributes']['role'] : 'all'; + if ($role === 'admin' && !$this->isAdmin()) { + continue; + } + $l = $this->l10nFac->get($app); + $order = isset($nav['order']) ? $nav['order'] : 100; + $route = $this->urlGenerator->linkToRoute($nav['route']); + $icon = isset($nav['icon']) ? $nav['icon'] : 'app.svg'; + foreach ([$icon, "$app.svg"] as $i) { + try { + $icon = $this->urlGenerator->imagePath($app, $i); + break; + } catch (\RuntimeException $ex) { + // no icon? - ignore it then + } + } + if (is_null($icon)) { + $icon = $this->urlGenerator->imagePath('core', 'default-app-icon'); + } + + $this->add([ + 'id' => $app, + 'order' => $order, + 'href' => $route, + 'icon' => $icon, + 'name' => $l->t($nav['name']), + ]); + } + } + + private function isAdmin() { + $user = $this->userSession->getUser(); + if ($user !== null) { + return $this->groupManager->isAdmin($user->getUID()); + } + return false; + } + } diff --git a/lib/private/Server.php b/lib/private/Server.php index a514534049d..bd8818e9460 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -316,8 +316,12 @@ class Server extends ServerContainer implements IServerContainer { return new \OC\Authentication\TwoFactorAuth\Manager($c->getAppManager(), $c->getSession(), $c->getConfig(), $c->getActivityManager(), $c->getLogger()); }); - $this->registerService('NavigationManager', function ($c) { - return new \OC\NavigationManager(); + $this->registerService('NavigationManager', function (Server $c) { + return new \OC\NavigationManager($c->getAppManager(), + $c->getURLGenerator(), + $c->getL10NFactory(), + $c->getUserSession(), + $c->getGroupManager()); }); $this->registerService('AllConfig', function (Server $c) { return new \OC\AllConfig( diff --git a/tests/lib/NavigationManagerTest.php b/tests/lib/NavigationManagerTest.php index 96708786e39..64fec802eca 100644 --- a/tests/lib/NavigationManagerTest.php +++ b/tests/lib/NavigationManagerTest.php @@ -12,7 +12,15 @@ namespace Test; +use OC\App\AppManager; use OC\NavigationManager; +use OCP\App\IAppManager; +use OCP\IGroupManager; +use OCP\IL10N; +use OCP\IURLGenerator; +use OCP\IUser; +use OCP\IUserSession; +use OCP\L10N\IFactory; class NavigationManagerTest extends TestCase { /** @var \OC\NavigationManager */ @@ -157,4 +165,62 @@ class NavigationManagerTest extends TestCase { $this->assertEmpty($this->navigationManager->getAll(), 'Expected no navigation entry exists after clear()'); $this->assertEquals(0, $testAddClosureNumberOfCalls, 'Expected that the closure is not called by getAll()'); } + + /** + * @dataProvider providesNavigationConfig + */ + public function testWithAppManager($expected, $config, $isAdmin = false) { + + $appManager = $this->createMock(AppManager::class); + $urlGenerator = $this->createMock(IURLGenerator::class); + $l10nFac = $this->createMock(IFactory::class); + $userSession = $this->createMock(IUserSession::class); + $groupManager = $this->createMock(IGroupManager::class); + $l = $this->createMock(IL10N::class); + $l->expects($this->any())->method('t')->willReturnCallback(function($text, $parameters = []) { + return vsprintf($text, $parameters); + }); + + $appManager->expects($this->once())->method('getInstalledApps')->willReturn(['test']); + $appManager->expects($this->once())->method('getAppInfo')->with('test')->willReturn($config); + $l10nFac->expects($this->exactly(count($expected)))->method('get')->with('test')->willReturn($l); + $urlGenerator->expects($this->any())->method('imagePath')->willReturnCallback(function($appName, $file) { + return "/apps/$appName/img/$file"; + }); + $urlGenerator->expects($this->exactly(count($expected)))->method('linkToRoute')->willReturnCallback(function($route) { + return "/apps/test/"; + }); + $user = $this->createMock(IUser::class); + $user->expects($this->any())->method('getUID')->willReturn('user001'); + $userSession->expects($this->any())->method('getUser')->willReturn($user); + $groupManager->expects($this->any())->method('isAdmin')->willReturn($isAdmin); + + $navigationManager = new NavigationManager($appManager, $urlGenerator, $l10nFac, $userSession, $groupManager); + + $entries = $navigationManager->getAll(); + $this->assertEquals($expected, $entries); + } + + public function providesNavigationConfig() { + return [ + 'minimalistic' => [[[ + 'id' => 'test', + 'order' => 100, + 'href' => '/apps/test/', + 'icon' => '/apps/test/img/app.svg', + 'name' => 'Test', + 'active' => false + ]], ['navigation' => ['route' => 'test.page.index', 'name' => 'Test']]], + 'no admin' => [[[ + 'id' => 'test', + 'order' => 100, + 'href' => '/apps/test/', + 'icon' => '/apps/test/img/app.svg', + 'name' => 'Test', + 'active' => false + ]], ['navigation' => ['@attributes' => ['role' => 'admin'], 'route' => 'test.page.index', 'name' => 'Test']], true], + 'no name' => [[], ['navigation' => ['@attributes' => ['role' => 'admin'], 'route' => 'test.page.index']], true], + 'admin' => [[], ['navigation' => ['@attributes' => ['role' => 'admin'], 'route' => 'test.page.index', 'name' => 'Test']]] + ]; + } } |