Merge pull request #2822 from nextcloud/add-navigation-via-info.xml
Add navigation via info.xml (#26785)
This commit is contained in:
commit
8b95bd29ee
|
@ -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();
|
||||||
|
|
|
@ -53,4 +53,11 @@
|
||||||
<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>
|
||||||
|
<name>Files</name>
|
||||||
|
<route>files.view.index</route>
|
||||||
|
<order>0</order>
|
||||||
|
</navigation>
|
||||||
|
|
||||||
</info>
|
</info>
|
||||||
|
|
|
@ -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>
|
After Width: | Height: | Size: 533 B |
|
@ -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,46 @@
|
||||||
|
|
||||||
namespace OC;
|
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
|
* 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|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
|
* Creates a new navigation entry
|
||||||
|
@ -60,6 +93,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 +105,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 +128,64 @@ 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['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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
return new \OC\Authentication\TwoFactorAuth\Manager($c->getAppManager(), $c->getSession(), $c->getConfig(), $c->getActivityManager(), $c->getLogger());
|
||||||
});
|
});
|
||||||
|
|
||||||
$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(
|
||||||
|
|
|
@ -12,7 +12,15 @@
|
||||||
|
|
||||||
namespace Test;
|
namespace Test;
|
||||||
|
|
||||||
|
use OC\App\AppManager;
|
||||||
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 +165,62 @@ 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(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']]]
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue