From aa8755bd4b2d5a949a35f1308eefa6d00140a1a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Thu, 8 Dec 2016 17:43:46 +0100 Subject: [PATCH] Add navigation via info.xml (#26785) * Read navigation information from info.xml * Load files navigation elements from info.xml * Add comment about ignoring the exception Signed-off-by: Lukas Reschke --- apps/files/appinfo/app.php | 14 +--- apps/files/appinfo/info.xml | 6 ++ apps/files/img/app.svg | 6 ++ lib/private/NavigationManager.php | 104 ++++++++++++++++++++++++++-- lib/private/Server.php | 8 ++- tests/lib/NavigationManagerTest.php | 64 +++++++++++++++++ 6 files changed, 182 insertions(+), 20 deletions(-) create mode 100644 apps/files/img/app.svg diff --git a/apps/files/appinfo/app.php b/apps/files/appinfo/app.php index a194bb5e79..63acda3a70 100644 --- a/apps/files/appinfo/app.php +++ b/apps/files/appinfo/app.php @@ -26,20 +26,10 @@ * along with this program. If not, see * */ +// 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 a25c043f33..1171c0ceb6 100644 --- a/apps/files/appinfo/info.xml +++ b/apps/files/appinfo/info.xml @@ -53,4 +53,10 @@ OCA\Files\Command\DeleteOrphanedFiles OCA\Files\Command\TransferOwnership + + + files.view.index + 0 + + diff --git a/apps/files/img/app.svg b/apps/files/img/app.svg new file mode 100644 index 0000000000..8f61739bc4 --- /dev/null +++ b/apps/files/img/app.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/lib/private/NavigationManager.php b/lib/private/NavigationManager.php index 3e9ddfc646..79b01a69c4 100644 --- a/lib/private/NavigationManager.php +++ b/lib/private/NavigationManager.php @@ -1,6 +1,6 @@ * @author Joas Schilling @@ -26,13 +26,45 @@ namespace OC; +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 */ + protected $appManager; + /** @var IURLGenerator */ + private $urlGenerator; + /** @var IFactory */ + private $l10nFac; + /** @var IUserSession */ + private $userSession; + /** @var IGroupManager */ + private $groupManager; + + 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 +92,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 +104,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 +127,62 @@ 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['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']); + $name = isset($nav['name']) ? $nav['name'] : ucfirst($app); + $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($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 969e5a25b9..9d411e5ef9 100644 --- a/lib/private/Server.php +++ b/lib/private/Server.php @@ -315,8 +315,12 @@ class Server extends ServerContainer implements IServerContainer { return new \OC\Authentication\TwoFactorAuth\Manager($c->getAppManager(), $c->getSession(), $c->getConfig()); }); - $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 96708786e3..942dcbe186 100644 --- a/tests/lib/NavigationManagerTest.php +++ b/tests/lib/NavigationManagerTest.php @@ -13,6 +13,13 @@ namespace Test; 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 +164,61 @@ 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(IAppManager::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']]], + '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']], true], + 'admin' => [[], ['navigation' => ['@attributes' => ['role' => 'admin'], 'route' => 'test.page.index']]] + ]; + } }