From 8ecac5654323e5d335386874f01b15d680d0febb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Julius=20H=C3=A4rtl?= <jus@bitgrid.net>
Date: Mon, 29 Jan 2018 12:52:40 +0100
Subject: [PATCH] Allow requesting absolute URLs
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

They might be useful when requesting the navigation from the clients

Signed-off-by: Julius Härtl <jus@bitgrid.net>
---
 core/Controller/NavigationController.php      | 38 ++++++++++++--
 .../Controller/NavigationControllerTest.php   | 49 ++++++++++++++++---
 2 files changed, 76 insertions(+), 11 deletions(-)

diff --git a/core/Controller/NavigationController.php b/core/Controller/NavigationController.php
index 5850025f450..98744171198 100644
--- a/core/Controller/NavigationController.php
+++ b/core/Controller/NavigationController.php
@@ -26,34 +26,62 @@ use OCP\AppFramework\Controller;
 use OCP\AppFramework\Http\JSONResponse;
 use OCP\INavigationManager;
 use OCP\IRequest;
+use OCP\IURLGenerator;
 
 class NavigationController extends Controller {
 
 	/** @var INavigationManager */
 	private $navigationManager;
 
-	public function __construct(string $appName, IRequest $request, INavigationManager $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 JSONResponse
 	 */
-	public function getAppsNavigation($absolute = false) {
-		return new JSONResponse($this->navigationManager->getAll('link', $absolute));
+	public function getAppsNavigation(bool $absolute = false) {
+		$navigation = $this->navigationManager->getAll('link');
+		if ($absolute) {
+			$this->rewriteToAbsoluteUrls($navigation);
+		}
+		return new JSONResponse($navigation);
 	}
 
 	/**
 	 * @NoAdminRequired
 	 * @NoCSRFRequired
 	 *
+	 * @param bool $absolute
 	 * @return JSONResponse
 	 */
-	public function getSettingsNavigation($absolute = false) {
-		return new JSONResponse($this->navigationManager->getAll('settings', $absolute));
+	public function getSettingsNavigation(bool $absolute = false) {
+		$navigation = $this->navigationManager->getAll('settings');
+		if ($absolute) {
+			$this->rewriteToAbsoluteUrls($navigation);
+		}
+		return new JSONResponse($navigation);
+	}
+
+	/**
+	 * Rewrite href attribute of navigation entries to an absolute URL
+	 *
+	 * @param array $navigation
+	 */
+	private function rewriteToAbsoluteUrls(array &$navigation) {
+		foreach ($navigation as &$entry) {
+			if (substr($entry['href'], 0, strlen($this->urlGenerator->getBaseUrl())) !== $this->urlGenerator->getBaseUrl()) {
+				$entry['href'] = $this->urlGenerator->getAbsoluteURL($entry['href']);
+			}
+		}
 	}
 }
diff --git a/tests/Core/Controller/NavigationControllerTest.php b/tests/Core/Controller/NavigationControllerTest.php
index 1e9acccb615..3a745b48678 100644
--- a/tests/Core/Controller/NavigationControllerTest.php
+++ b/tests/Core/Controller/NavigationControllerTest.php
@@ -26,6 +26,7 @@ use OC\Core\Controller\NavigationController;
 use OCP\AppFramework\Http\JSONResponse;
 use OCP\INavigationManager;
 use OCP\IRequest;
+use OCP\IURLGenerator;
 use Test\TestCase;
 
 class NavigationControllerTest extends TestCase {
@@ -36,20 +37,24 @@ class NavigationControllerTest extends TestCase {
 	/** @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->navigationManager,
+			$this->urlGenerator
 		);
 	}
 
@@ -62,16 +67,48 @@ class NavigationControllerTest extends TestCase {
 	public function testGetAppNavigation($absolute) {
 		$this->navigationManager->expects($this->once())
 			->method('getAll')
-			->with('link', $absolute);
-		$this->assertInstanceOf(JSONResponse::class, $this->controller->getAppsNavigation($absolute));
+			->with('link')
+			->willReturn([ ['id' => 'files', 'href' => '/index.php/apps/files'] ]);
+		if ($absolute) {
+			$this->urlGenerator->expects($this->any())
+				->method('getBaseURL')
+				->willReturn('http://localhost/');
+			$this->urlGenerator->expects($this->once())
+				->method('getAbsoluteURL')
+				->with('/index.php/apps/files')
+				->willReturn('http://localhost/index.php/apps/files');
+			$actual = $this->controller->getAppsNavigation($absolute);
+			$this->assertInstanceOf(JSONResponse::class, $actual);
+			$this->assertEquals('http://localhost/index.php/apps/files', $actual->getData()[0]['href']);
+		} else {
+			$actual = $this->controller->getAppsNavigation($absolute);
+			$this->assertInstanceOf(JSONResponse::class, $actual);
+			$this->assertEquals('/index.php/apps/files', $actual->getData()[0]['href']);
+		}
 	}
 
 	/** @dataProvider dataGetNavigation */
 	public function testGetSettingsNavigation($absolute) {
 		$this->navigationManager->expects($this->once())
 			->method('getAll')
-			->with('settings', $absolute);
-		$this->assertInstanceOf(JSONResponse::class, $this->controller->getSettingsNavigation($absolute));
+			->with('settings')
+			->willReturn([ ['id' => 'settings', 'href' => '/index.php/settings/user'] ]);
+		if ($absolute) {
+			$this->urlGenerator->expects($this->any())
+				->method('getBaseURL')
+				->willReturn('http://localhost/');
+			$this->urlGenerator->expects($this->once())
+				->method('getAbsoluteURL')
+				->with('/index.php/settings/user')
+				->willReturn('http://localhost/index.php/settings/user');
+			$actual = $this->controller->getSettingsNavigation($absolute);
+			$this->assertInstanceOf(JSONResponse::class, $actual);
+			$this->assertEquals('http://localhost/index.php/settings/user', $actual->getData()[0]['href']);
+		} else {
+			$actual = $this->controller->getSettingsNavigation($absolute);
+			$this->assertInstanceOf(JSONResponse::class, $actual);
+			$this->assertEquals('/index.php/settings/user', $actual->getData()[0]['href']);
+		}
 	}
 
 }
-- 
GitLab