summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMorris Jobke <hey@morrisjobke.de>2018-02-15 16:55:12 +0100
committerGitHub <noreply@github.com>2018-02-15 16:55:12 +0100
commit14bc9b171427c1512226d5ea402021d8b44ac690 (patch)
tree1a4b9c64f711becf429f90da69d3d46279c55435
parent8a505e8767fe7af62a4e9e8d95ef2e336b05bf61 (diff)
parente694b30a4f1e1cce6cbca0fcbbfeceee8a16c8f6 (diff)
downloadnextcloud-server-14bc9b171427c1512226d5ea402021d8b44ac690.tar.gz
nextcloud-server-14bc9b171427c1512226d5ea402021d8b44ac690.zip
Merge pull request #8095 from nextcloud/webapps-capabilities
Expose navigation entries as API endpoint
-rw-r--r--core/Controller/NavigationController.php92
-rw-r--r--core/routes.php2
-rw-r--r--lib/composer/composer/autoload_classmap.php1
-rw-r--r--lib/composer/composer/autoload_static.php1
-rw-r--r--lib/private/NavigationManager.php51
-rw-r--r--lib/private/TemplateLayout.php4
-rw-r--r--lib/private/legacy/app.php33
-rw-r--r--lib/public/INavigationManager.php9
-rw-r--r--settings/ajax/navigationdetect.php2
-rw-r--r--tests/Core/Controller/NavigationControllerTest.php129
-rw-r--r--tests/lib/NavigationManagerTest.php14
11 files changed, 291 insertions, 47 deletions
diff --git a/core/Controller/NavigationController.php b/core/Controller/NavigationController.php
new file mode 100644
index 00000000000..3521fac3b46
--- /dev/null
+++ b/core/Controller/NavigationController.php
@@ -0,0 +1,92 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
+ *
+ * @author Julius Härtl <jus@bitgrid.net>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+namespace OC\Core\Controller;
+
+use OCP\AppFramework\Http\DataResponse;
+use OCP\AppFramework\OCSController;
+use OCP\INavigationManager;
+use OCP\IRequest;
+use OCP\IURLGenerator;
+
+class NavigationController extends OCSController {
+
+ /** @var INavigationManager */
+ private $navigationManager;
+
+ /** @var IURLGenerator */
+ private $urlGenerator;
+
+ public function __construct(string $appName, IRequest $request, INavigationManager $navigationManager, IURLGenerator $urlGenerator) {
+ parent::__construct($appName, $request);
+ $this->navigationManager = $navigationManager;
+ $this->urlGenerator = $urlGenerator;
+ }
+
+ /**
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ *
+ * @param bool $absolute
+ * @return DataResponse
+ */
+ public function getAppsNavigation(bool $absolute = false): DataResponse {
+ $navigation = $this->navigationManager->getAll();
+ if ($absolute) {
+ $navigation = $this->rewriteToAbsoluteUrls($navigation);
+ }
+ return new DataResponse($navigation);
+ }
+
+ /**
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ *
+ * @param bool $absolute
+ * @return DataResponse
+ */
+ public function getSettingsNavigation(bool $absolute = false): DataResponse {
+ $navigation = $this->navigationManager->getAll('settings');
+ if ($absolute) {
+ $navigation = $this->rewriteToAbsoluteUrls($navigation);
+ }
+ return new DataResponse($navigation);
+ }
+
+ /**
+ * Rewrite href attribute of navigation entries to an absolute URL
+ *
+ * @param array $navigation
+ * @return array
+ */
+ private function rewriteToAbsoluteUrls(array $navigation): array {
+ foreach ($navigation as &$entry) {
+ if (0 !== strpos($entry['href'], $this->urlGenerator->getBaseUrl())) {
+ $entry['href'] = $this->urlGenerator->getAbsoluteURL($entry['href']);
+ }
+ if (0 !== strpos($entry['icon'], $this->urlGenerator->getBaseUrl())) {
+ $entry['icon'] = $this->urlGenerator->getAbsoluteURL($entry['icon']);
+ }
+ }
+ return $navigation;
+ }
+}
diff --git a/core/routes.php b/core/routes.php
index 0eed8ed1796..97a8621fc39 100644
--- a/core/routes.php
+++ b/core/routes.php
@@ -71,6 +71,8 @@ $application->registerRoutes($this, [
['root' => '', 'name' => 'OCS#getConfig', 'url' => '/config', 'verb' => 'GET'],
['root' => '/person', 'name' => 'OCS#personCheck', 'url' => '/check', 'verb' => 'POST'],
['root' => '/identityproof', 'name' => 'OCS#getIdentityProof', 'url' => '/key/{cloudId}', 'verb' => 'GET'],
+ ['root' => '/core', 'name' => 'Navigation#getAppsNavigation', 'url' => '/navigation/apps', 'verb' => 'GET'],
+ ['root' => '/core', 'name' => 'Navigation#getSettingsNavigation', 'url' => '/navigation/settings', 'verb' => 'GET'],
],
]);
diff --git a/lib/composer/composer/autoload_classmap.php b/lib/composer/composer/autoload_classmap.php
index 3eb532be0c6..06879c5179a 100644
--- a/lib/composer/composer/autoload_classmap.php
+++ b/lib/composer/composer/autoload_classmap.php
@@ -521,6 +521,7 @@ return array(
'OC\\Core\\Controller\\JsController' => $baseDir . '/core/Controller/JsController.php',
'OC\\Core\\Controller\\LoginController' => $baseDir . '/core/Controller/LoginController.php',
'OC\\Core\\Controller\\LostController' => $baseDir . '/core/Controller/LostController.php',
+ 'OC\\Core\\Controller\\NavigationController' => $baseDir . '/core/Controller/NavigationController.php',
'OC\\Core\\Controller\\OCJSController' => $baseDir . '/core/Controller/OCJSController.php',
'OC\\Core\\Controller\\OCSController' => $baseDir . '/core/Controller/OCSController.php',
'OC\\Core\\Controller\\PreviewController' => $baseDir . '/core/Controller/PreviewController.php',
diff --git a/lib/composer/composer/autoload_static.php b/lib/composer/composer/autoload_static.php
index 2483b5689b3..118094c30ef 100644
--- a/lib/composer/composer/autoload_static.php
+++ b/lib/composer/composer/autoload_static.php
@@ -551,6 +551,7 @@ class ComposerStaticInit53792487c5a8370acc0b06b1a864ff4c
'OC\\Core\\Controller\\JsController' => __DIR__ . '/../../..' . '/core/Controller/JsController.php',
'OC\\Core\\Controller\\LoginController' => __DIR__ . '/../../..' . '/core/Controller/LoginController.php',
'OC\\Core\\Controller\\LostController' => __DIR__ . '/../../..' . '/core/Controller/LostController.php',
+ 'OC\\Core\\Controller\\NavigationController' => __DIR__ . '/../../..' . '/core/Controller/NavigationController.php',
'OC\\Core\\Controller\\OCJSController' => __DIR__ . '/../../..' . '/core/Controller/OCJSController.php',
'OC\\Core\\Controller\\OCSController' => __DIR__ . '/../../..' . '/core/Controller/OCSController.php',
'OC\\Core\\Controller\\PreviewController' => __DIR__ . '/../../..' . '/core/Controller/PreviewController.php',
diff --git a/lib/private/NavigationManager.php b/lib/private/NavigationManager.php
index 31d147a3b80..279c899c5fa 100644
--- a/lib/private/NavigationManager.php
+++ b/lib/private/NavigationManager.php
@@ -104,26 +104,61 @@ class NavigationManager implements INavigationManager {
}
/**
- * returns all the added Menu entries
- * @param string $type
- * @return array an array of the added entries
+ * Get a list of navigation entries
+ *
+ * @param string $type type of the navigation entries
+ * @return array
*/
- public function getAll($type = 'link') {
+ public function getAll(string $type = 'link'): array {
$this->init();
foreach ($this->closureEntries as $c) {
$this->add($c());
}
$this->closureEntries = array();
- if ($type === 'all') {
- return $this->entries;
+ $result = $this->entries;
+ if ($type !== 'all') {
+ $result = array_filter($this->entries, function($entry) use ($type) {
+ return $entry['type'] === $type;
+ });
}
- return array_filter($this->entries, function($entry) use ($type) {
- return $entry['type'] === $type;
+ return $this->proceedNavigation($result);
+ }
+
+ /**
+ * Sort navigation entries by order, name and set active flag
+ *
+ * @param array $list
+ * @return array
+ */
+ private function proceedNavigation(array $list): array {
+ usort($list, function($a, $b) {
+ if (isset($a['order']) && isset($b['order'])) {
+ return ($a['order'] < $b['order']) ? -1 : 1;
+ } else if (isset($a['order']) || isset($b['order'])) {
+ return isset($a['order']) ? -1 : 1;
+ } else {
+ return ($a['name'] < $b['name']) ? -1 : 1;
+ }
});
+
+ $activeApp = $this->getActiveEntry();
+ if ($activeApp !== null) {
+ foreach ($list as $index => &$navEntry) {
+ if ($navEntry['id'] == $activeApp) {
+ $navEntry['active'] = true;
+ } else {
+ $navEntry['active'] = false;
+ }
+ }
+ unset($navEntry);
+ }
+
+ return $list;
}
+
/**
* removes all the entries
*/
diff --git a/lib/private/TemplateLayout.php b/lib/private/TemplateLayout.php
index d37a8bbabbe..8cc235bf818 100644
--- a/lib/private/TemplateLayout.php
+++ b/lib/private/TemplateLayout.php
@@ -80,9 +80,9 @@ class TemplateLayout extends \OC_Template {
// Add navigation entry
$this->assign( 'application', '');
$this->assign( 'appid', $appId );
- $navigation = \OC_App::getNavigation();
+ $navigation = \OC::$server->getNavigationManager()->getAll();
$this->assign( 'navigation', $navigation);
- $settingsNavigation = \OC_App::getSettingsNavigation();
+ $settingsNavigation = \OC::$server->getNavigationManager()->getAll('settings');
$this->assign( 'settingsnavigation', $settingsNavigation);
foreach($navigation as $entry) {
if ($entry['active']) {
diff --git a/lib/private/legacy/app.php b/lib/private/legacy/app.php
index 9384582bac3..f97b74ed24f 100644
--- a/lib/private/legacy/app.php
+++ b/lib/private/legacy/app.php
@@ -445,31 +445,6 @@ class OC_App {
$appManager->disableApp($app);
}
- // This is private as well. It simply works, so don't ask for more details
- private static function proceedNavigation($list) {
- usort($list, function($a, $b) {
- if (isset($a['order']) && isset($b['order'])) {
- return ($a['order'] < $b['order']) ? -1 : 1;
- } else if (isset($a['order']) || isset($b['order'])) {
- return isset($a['order']) ? -1 : 1;
- } else {
- return ($a['name'] < $b['name']) ? -1 : 1;
- }
- });
-
- $activeApp = OC::$server->getNavigationManager()->getActiveEntry();
- foreach ($list as $index => &$navEntry) {
- if ($navEntry['id'] == $activeApp) {
- $navEntry['active'] = true;
- } else {
- $navEntry['active'] = false;
- }
- }
- unset($navEntry);
-
- return $list;
- }
-
/**
* Get the path where to install apps
*
@@ -613,6 +588,7 @@ class OC_App {
* Returns the navigation
*
* @return array
+ * @deprecated 14.0.0 use \OC::$server->getNavigationManager()->getAll()
*
* This function returns an array containing all entries added. The
* entries are sorted by the key 'order' ascending. Additional to the keys
@@ -620,21 +596,20 @@ class OC_App {
* - active: boolean, signals if the user is on this navigation entry
*/
public static function getNavigation() {
- $entries = OC::$server->getNavigationManager()->getAll();
- return self::proceedNavigation($entries);
+ return OC::$server->getNavigationManager()->getAll();
}
/**
* Returns the Settings Navigation
*
* @return string[]
+ * @deprecated 14.0.0 use \OC::$server->getNavigationManager()->getAll('settings')
*
* This function returns an array containing all settings pages added. The
* entries are sorted by the key 'order' ascending.
*/
public static function getSettingsNavigation() {
- $entries = OC::$server->getNavigationManager()->getAll('settings');
- return self::proceedNavigation($entries);
+ return OC::$server->getNavigationManager()->getAll('settings');
}
/**
diff --git a/lib/public/INavigationManager.php b/lib/public/INavigationManager.php
index 216f8a897d8..77b881b8b15 100644
--- a/lib/public/INavigationManager.php
+++ b/lib/public/INavigationManager.php
@@ -57,4 +57,13 @@ interface INavigationManager {
* @since 6.0.0
*/
public function setActiveEntry($appId);
+
+ /**
+ * Get a list of navigation entries
+ *
+ * @param string $type type of the navigation entries
+ * @return array
+ * @since 14.0.0
+ */
+ public function getAll(string $type = 'link'): array;
}
diff --git a/settings/ajax/navigationdetect.php b/settings/ajax/navigationdetect.php
index 167f819f91e..043e10da559 100644
--- a/settings/ajax/navigationdetect.php
+++ b/settings/ajax/navigationdetect.php
@@ -23,6 +23,6 @@
OC_Util::checkAdminUser();
OCP\JSON::callCheck();
-$navigation = \OC_App::getNavigation();
+$navigation = \OC::$server->getNavigationManager()->getAll();
OCP\JSON::success(['nav_entries' => $navigation]);
diff --git a/tests/Core/Controller/NavigationControllerTest.php b/tests/Core/Controller/NavigationControllerTest.php
new file mode 100644
index 00000000000..1143ed003f0
--- /dev/null
+++ b/tests/Core/Controller/NavigationControllerTest.php
@@ -0,0 +1,129 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
+ *
+ * @author Julius Härtl <jus@bitgrid.net>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+namespace Tests\Core\Controller;
+
+use OC\Core\Controller\NavigationController;
+use OCP\AppFramework\Http\DataResponse;
+use OCP\INavigationManager;
+use OCP\IRequest;
+use OCP\IURLGenerator;
+use Test\TestCase;
+
+class NavigationControllerTest extends TestCase {
+
+ /** @var IRequest|\PHPUnit_Framework_MockObject_MockObject */
+ private $request;
+
+ /** @var INavigationManager|\PHPUnit_Framework_MockObject_MockObject */
+ private $navigationManager;
+
+ /** @var IURLGenerator|\PHPUnit_Framework_MockObject_MockObject */
+ private $urlGenerator;
+
+ /** @var NavigationController */
+ private $controller;
+
+ public function setUp() {
+ parent::setUp();
+
+ $this->request = $this->createMock(IRequest::class);
+ $this->navigationManager = $this->createMock(INavigationManager::class);
+ $this->urlGenerator = $this->createMock(IURLGenerator::class);
+
+ $this->controller = new NavigationController(
+ 'core',
+ $this->request,
+ $this->navigationManager,
+ $this->urlGenerator
+ );
+ }
+
+ public function dataGetNavigation() {
+ return [
+ [false], [true]
+ ];
+ }
+ /** @dataProvider dataGetNavigation */
+ public function testGetAppNavigation($absolute) {
+ $this->navigationManager->expects($this->once())
+ ->method('getAll')
+ ->with('link')
+ ->willReturn([ ['id' => 'files', 'href' => '/index.php/apps/files', 'icon' => 'icon' ] ]);
+ if ($absolute) {
+ $this->urlGenerator->expects($this->any())
+ ->method('getBaseURL')
+ ->willReturn('http://localhost/');
+ $this->urlGenerator->expects($this->at(1))
+ ->method('getAbsoluteURL')
+ ->with('/index.php/apps/files')
+ ->willReturn('http://localhost/index.php/apps/files');
+ $this->urlGenerator->expects($this->at(3))
+ ->method('getAbsoluteURL')
+ ->with('icon')
+ ->willReturn('http://localhost/icon');
+ $actual = $this->controller->getAppsNavigation($absolute);
+ $this->assertInstanceOf(DataResponse::class, $actual);
+ $this->assertEquals('http://localhost/index.php/apps/files', $actual->getData()[0]['href']);
+ $this->assertEquals('http://localhost/icon', $actual->getData()[0]['icon']);
+
+
+ } else {
+ $actual = $this->controller->getAppsNavigation($absolute);
+ $this->assertInstanceOf(DataResponse::class, $actual);
+ $this->assertEquals('/index.php/apps/files', $actual->getData()[0]['href']);
+ $this->assertEquals('icon', $actual->getData()[0]['icon']);
+
+ }
+ }
+
+ /** @dataProvider dataGetNavigation */
+ public function testGetSettingsNavigation($absolute) {
+ $this->navigationManager->expects($this->once())
+ ->method('getAll')
+ ->with('settings')
+ ->willReturn([ ['id' => 'settings', 'href' => '/index.php/settings/user', 'icon' => '/core/img/settings.svg'] ]);
+ if ($absolute) {
+ $this->urlGenerator->expects($this->any())
+ ->method('getBaseURL')
+ ->willReturn('http://localhost/');
+ $this->urlGenerator->expects($this->at(1))
+ ->method('getAbsoluteURL')
+ ->with('/index.php/settings/user')
+ ->willReturn('http://localhost/index.php/settings/user');
+ $this->urlGenerator->expects($this->at(3))
+ ->method('getAbsoluteURL')
+ ->with('/core/img/settings.svg')
+ ->willReturn('http://localhost/core/img/settings.svg');
+ $actual = $this->controller->getSettingsNavigation($absolute);
+ $this->assertInstanceOf(DataResponse::class, $actual);
+ $this->assertEquals('http://localhost/index.php/settings/user', $actual->getData()[0]['href']);
+ $this->assertEquals('http://localhost/core/img/settings.svg', $actual->getData()[0]['icon']);
+ } else {
+ $actual = $this->controller->getSettingsNavigation($absolute);
+ $this->assertInstanceOf(DataResponse::class, $actual);
+ $this->assertEquals('/index.php/settings/user', $actual->getData()[0]['href']);
+ $this->assertEquals('/core/img/settings.svg', $actual->getData()[0]['icon']);
+ }
+ }
+
+}
diff --git a/tests/lib/NavigationManagerTest.php b/tests/lib/NavigationManagerTest.php
index 585161c887b..b34ecca9469 100644
--- a/tests/lib/NavigationManagerTest.php
+++ b/tests/lib/NavigationManagerTest.php
@@ -284,7 +284,7 @@ class NavigationManagerTest extends TestCase {
],
];
return [
- 'minimalistic' => [array_merge($defaults, [[
+ 'minimalistic' => [array_merge([$defaults[0]], [[
'id' => 'test',
'order' => 100,
'href' => '/apps/test/',
@@ -293,8 +293,8 @@ class NavigationManagerTest extends TestCase {
'active' => false,
'type' => 'link',
'classes' => '',
- ]]), ['navigations' => [['route' => 'test.page.index', 'name' => 'Test']]]],
- 'minimalistic-settings' => [array_merge($defaults, [[
+ ]], [$defaults[1]]), ['navigations' => [['route' => 'test.page.index', 'name' => 'Test']]]],
+ 'minimalistic-settings' => [array_merge([$defaults[0]], [[
'id' => 'test',
'order' => 100,
'href' => '/apps/test/',
@@ -303,8 +303,8 @@ class NavigationManagerTest extends TestCase {
'active' => false,
'type' => 'settings',
'classes' => '',
- ]]), ['navigations' => [['route' => 'test.page.index', 'name' => 'Test', 'type' => 'settings']]]],
- 'admin' => [array_merge($apps, $defaults, [[
+ ]], [$defaults[1]]), ['navigations' => [['route' => 'test.page.index', 'name' => 'Test', 'type' => 'settings']]]],
+ 'admin' => [array_merge([$defaults[0]], $apps, [[
'id' => 'test',
'order' => 100,
'href' => '/apps/test/',
@@ -313,8 +313,8 @@ class NavigationManagerTest extends TestCase {
'active' => false,
'type' => 'link',
'classes' => '',
- ]]), ['navigations' => [['@attributes' => ['role' => 'admin'], 'route' => 'test.page.index', 'name' => 'Test']]], true],
- 'no name' => [array_merge($apps, $defaults), ['navigations' => [['@attributes' => ['role' => 'admin'], 'route' => 'test.page.index']]], true],
+ ]], [$defaults[1]]), ['navigations' => [['@attributes' => ['role' => 'admin'], 'route' => 'test.page.index', 'name' => 'Test']]], true],
+ 'no name' => [array_merge([$defaults[0]], $apps, [$defaults[1]]), ['navigations' => [['@attributes' => ['role' => 'admin'], 'route' => 'test.page.index']]], true],
'no admin' => [$defaults, ['navigations' => [['@attributes' => ['role' => 'admin'], 'route' => 'test.page.index', 'name' => 'Test']]]]
];
}