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 <lukas@statuscode.ch>
This commit is contained in:
Thomas Müller 2016-12-08 17:43:46 +01:00 committed by Lukas Reschke
parent 7f8d22e710
commit aa8755bd4b
No known key found for this signature in database
GPG Key ID: B9F6980CF6E759B1
6 changed files with 182 additions and 20 deletions

View File

@ -26,20 +26,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/> * along with this program. If not, see <http://www.gnu.org/licenses/>
* *
*/ */
// required for translation purpose
// t('Files')
$l = \OC::$server->getL10N('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'))); \OC::$server->getSearch()->registerProvider('OC\Search\Provider\File', array('apps' => array('files')));
$templateManager = \OC_Helper::getFileTemplateManager(); $templateManager = \OC_Helper::getFileTemplateManager();

View File

@ -53,4 +53,10 @@
<command>OCA\Files\Command\DeleteOrphanedFiles</command> <command>OCA\Files\Command\DeleteOrphanedFiles</command>
<command>OCA\Files\Command\TransferOwnership</command> <command>OCA\Files\Command\TransferOwnership</command>
</commands> </commands>
<navigation>
<route>files.view.index</route>
<order>0</order>
</navigation>
</info> </info>

6
apps/files/img/app.svg Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="32" width="32" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
<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>

After

Width:  |  Height:  |  Size: 655 B

View File

@ -1,6 +1,6 @@
<?php <?php
/** /**
* @copyright Copyright (c) 2016, ownCloud, Inc. * @copyright Copyright (c) 2016, ownCloud GmbH
* *
* @author Bart Visscher <bartv@thisnet.nl> * @author Bart Visscher <bartv@thisnet.nl>
* @author Joas Schilling <coding@schilljs.com> * @author Joas Schilling <coding@schilljs.com>
@ -26,13 +26,45 @@
namespace OC; 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 * Manages the ownCloud navigation
*/ */
class NavigationManager implements \OCP\INavigationManager {
protected $entries = array(); class NavigationManager implements INavigationManager {
protected $closureEntries = array(); protected $entries = [];
protected $closureEntries = [];
protected $activeEntry; 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 * Creates a new navigation entry
@ -60,6 +92,7 @@ class NavigationManager implements \OCP\INavigationManager {
* @return array an array of the added entries * @return array an array of the added entries
*/ */
public function getAll() { public function getAll() {
$this->init();
foreach ($this->closureEntries as $c) { foreach ($this->closureEntries as $c) {
$this->add($c()); $this->add($c());
} }
@ -71,8 +104,9 @@ class NavigationManager implements \OCP\INavigationManager {
* removes all the entries * removes all the entries
*/ */
public function clear() { public function clear() {
$this->entries = array(); $this->entries = [];
$this->closureEntries = array(); $this->closureEntries = [];
$this->init = false;
} }
/** /**
@ -93,4 +127,62 @@ class NavigationManager implements \OCP\INavigationManager {
public function getActiveEntry() { public function getActiveEntry() {
return $this->activeEntry; 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;
}
} }

View File

@ -315,8 +315,12 @@ class Server extends ServerContainer implements IServerContainer {
return new \OC\Authentication\TwoFactorAuth\Manager($c->getAppManager(), $c->getSession(), $c->getConfig()); return new \OC\Authentication\TwoFactorAuth\Manager($c->getAppManager(), $c->getSession(), $c->getConfig());
}); });
$this->registerService('NavigationManager', function ($c) { $this->registerService('NavigationManager', function (Server $c) {
return new \OC\NavigationManager(); return new \OC\NavigationManager($c->getAppManager(),
$c->getURLGenerator(),
$c->getL10NFactory(),
$c->getUserSession(),
$c->getGroupManager());
}); });
$this->registerService('AllConfig', function (Server $c) { $this->registerService('AllConfig', function (Server $c) {
return new \OC\AllConfig( return new \OC\AllConfig(

View File

@ -13,6 +13,13 @@
namespace Test; namespace Test;
use OC\NavigationManager; 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 { class NavigationManagerTest extends TestCase {
/** @var \OC\NavigationManager */ /** @var \OC\NavigationManager */
@ -157,4 +164,61 @@ class NavigationManagerTest extends TestCase {
$this->assertEmpty($this->navigationManager->getAll(), 'Expected no navigation entry exists after clear()'); $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()'); $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']]]
];
}
} }