diff --git a/.travis.yml b/.travis.yml index 4e738ad..9241747 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,9 +7,9 @@ env: global: - DB=sqlite matrix: - - CORE_BRANCH=stable9 REPO=owncloud/core + - CORE_BRANCH=stable9.1 REPO=owncloud/core - CORE_BRANCH=master REPO=owncloud/core - - CORE_BRANCH=stable9 REPO=nextcloud/server + - CORE_BRANCH=stable10 REPO=nextcloud/server - CORE_BRANCH=master REPO=nextcloud/server matrix: diff --git a/README.md b/README.md index f51a87e..952172b 100644 --- a/README.md +++ b/README.md @@ -12,4 +12,24 @@ app. ![AppOrder in Action](https://bitgrid.net/~jus/apporder.gif) -**This app is still work in progress.** + +## Set a default order for all new users + +Go to the Admin settings > Additional settings and drag the icons under App order. + +## Use first app as default app + +You can easily let Nextcloud redirect your user to the first app in their +personal order by changing the following parameter in your config/config.php: + + 'defaultapp' => 'apporder', + +Users will now get redirected to the first app of the default order or to the +first app of the user order. + +# Installation + +## From git + +1. Clone the app into your apps/ directory: `git clone https://github.com/juliushaertl/apporder.git` +2. Enable it diff --git a/appinfo/app.php b/appinfo/app.php deleted file mode 100644 index 8096f1b..0000000 --- a/appinfo/app.php +++ /dev/null @@ -1,7 +0,0 @@ -getContainer(); - $container->registerService('ConfigService', function($c) { - return new ConfigService( - $c->query('Config'), - $c->query('AppName') - ); - }); - - } -} diff --git a/appinfo/autoload.php b/appinfo/autoload.php index 6139922..737046e 100644 --- a/appinfo/autoload.php +++ b/appinfo/autoload.php @@ -1,20 +1,25 @@ * - * This file is licensed under the Affero General Public License version 3 or - * later. See the COPYING file. + * @author Julius Härtl + * + * @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 . * - * @author jus - * @copyright jus 2016 */ - namespace OCA\AppOrder\AppInfo; -use OCA\AppOrder\AppInfo\Application; use OCP\AppFramework\App; - -/** - * Additional autoloader registration, e.g. registering composer autoloaders - */ -// require_once __DIR__ . '/../vendor/autoload.php'; diff --git a/appinfo/info.xml b/appinfo/info.xml index 4071b1c..7942aa5 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -9,6 +9,7 @@ + AppOrder https://github.com/juliushaertl/apporder.git 174715 diff --git a/appinfo/routes.php b/appinfo/routes.php index e4a9afb..ec64a50 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -1,11 +1,10 @@ registerRoutes($this, [ +return [ 'routes' => [ + ['name' => 'app#index', 'url' => '/', 'verb' => 'GET'], ['name' => 'settings#getOrder', 'url' => 'ajax/order.php', 'verb' => 'GET'], ['name' => 'settings#savePersonal', 'url' => 'ajax/personal.php', 'verb' => 'GET'], ['name' => 'settings#saveDefaultOrder', 'url' => 'ajax/admin.php', 'verb' => 'GET'], ] -]); +]; diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php new file mode 100644 index 0000000..275a5df --- /dev/null +++ b/lib/AppInfo/Application.php @@ -0,0 +1,45 @@ + + * + * @author Julius Härtl + * + * @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 . + * + */ + +namespace OCA\AppOrder\AppInfo; + +use \OCP\AppFramework\App; +use \OCA\AppOrder\Service\ConfigService; + +class Application extends App { + + public function __construct(array $urlParams = array()) { + parent::__construct('apporder', $urlParams); + $container = $this->getContainer(); + $container->registerService('ConfigService', function($c) { + return new ConfigService( + $c->query('Config'), + $c->query('AppName') + ); + }); + + \OCP\Util::addStyle('apporder', 'apporder'); + \OCP\Util::addScript('apporder', 'apporder'); + \OCP\App::registerAdmin('apporder', 'admin'); + } +} diff --git a/lib/Controller/AppController.php b/lib/Controller/AppController.php new file mode 100644 index 0000000..20de25c --- /dev/null +++ b/lib/Controller/AppController.php @@ -0,0 +1,68 @@ + + * + * @author Julius Härtl + * + * @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 . + * + */ + +namespace OCA\AppOrder\Controller; + +use \OCP\AppFramework\Controller; +use OCP\AppFramework\Http\RedirectResponse; +use \OCP\IRequest; +use \OCP\INavigationManager; +use \OCA\AppOrder\Service\ConfigService; +use OCA\AppOrder\Util; +use OCP\IURLGenerator; + +class AppController extends Controller { + + private $userId; + private $appConfig; + private $urlGenerator; + private $util; + + public function __construct($appName, IRequest $request, ConfigService $appConfig, IURLGenerator $urlGenerator, Util $util, $userId) { + parent::__construct($appName, $request); + $this->userId = $userId; + $this->appConfig = $appConfig; + $this->urlGenerator = $urlGenerator; + $this->util = $util; + } + + /** + * @NoCSRFRequired + * @return RedirectResponse + */ + public function index() { + $order = json_decode($this->util->getAppOrder()); + if($order !== null && sizeof($order)>0) { + $firstPage = $order[0]; + } else { + $appId = 'files'; + if(getenv('front_controller_active') === 'true') { + $firstPage = $this->urlGenerator->getAbsoluteURL('/apps/' . $appId . '/'); + } else { + $firstPage = $this->urlGenerator->getAbsoluteURL('/index.php/apps/' . $appId . '/'); + } + } + return new RedirectResponse($firstPage); + } + +} diff --git a/controller/settingscontroller.php b/lib/Controller/SettingsController.php similarity index 50% rename from controller/settingscontroller.php rename to lib/Controller/SettingsController.php index 3f36f41..f4186ec 100644 --- a/controller/settingscontroller.php +++ b/lib/Controller/SettingsController.php @@ -7,25 +7,33 @@ use \OCP\IRequest; use \OCP\INavigationManager; use \OCA\AppOrder\Service\ConfigService; +use \OCA\AppOrder\Util; class SettingsController extends Controller { private $userId; - private $l10n; private $appConfig; private $navigationManager; + private $util; - public function __construct($appName, IRequest $request, ConfigService $appConfig, INavigationManager $navigationManager, $userId) { + public function __construct($appName, IRequest $request, ConfigService $appConfig, INavigationManager $urlGenerator, Util $util, $userId) { parent::__construct($appName, $request); $this->userId = $userId; $this->appConfig = $appConfig; - $this->navigationManager = $navigationManager; + $this->navigationManager = $urlGenerator; + $this->util = $util; } + /** + * Admin: render admin page + * FIXME: Move to dedicated class + * @return TemplateResponse + */ public function adminIndex() { + // Private API call $navigation = $this->navigationManager->getAll(); $order = json_decode($this->appConfig->getAppValue('order')); - $nav = $this->matchOrder($navigation, $order); + $nav = $this->util->matchOrder($navigation, $order); return new TemplateResponse( $this->appName, 'admin', @@ -34,41 +42,31 @@ public function adminIndex() { ); } - public function getAppOrder() { - $order_user = $this->appConfig->getUserValue('order', $this->userId); - $order_default = $this->appConfig->getAppValue('order'); - if ($order_user !== null && $order_user !== "") - $order = $order_user; - else - $order = $order_default; - return $order; - } - - public function matchOrder($nav, $order) { - $nav_tmp = array(); - $result = array(); - foreach ($nav as $app) - $nav_tmp[$app['href']] = $app; - foreach ($order as $app) - if(array_key_exists($app, $nav_tmp)) - $result[$app] = $nav_tmp[$app]; - foreach ($nav as $app) - if (!array_key_exists($app['href'], $result)) - $result[$app['href']] = $app; - return $result; - } + /** + * Admin: save default order + * @param $order + * @return array + */ + public function saveDefaultOrder($order) { + if (!is_null($order)) { + $this->appConfig->setAppValue('order', $order); + } + return array('status' => 'success', 'order' => $order); + } /** * @NoAdminRequired */ public function getOrder() { - $order = $this->getAppOrder(); + $order = $this->util->getAppOrder(); return array('status' => 'success', 'order' => $order); } - /** - * @NoAdminRequired - */ + /** + * @NoAdminRequired + * @param $order string + * @return array response + */ public function savePersonal($order) { $this->appConfig->setUserValue('order', $this->userId, $order); $response = array( @@ -79,10 +77,5 @@ public function savePersonal($order) { return $response; } - public function saveDefaultOrder($order) { - if (!is_null($order)) { - $this->appConfig->setAppValue('order', $order); - } - return array('status' => 'success', 'order' => $order); - } + } diff --git a/service/configservice.php b/lib/Service/ConfigService.php similarity index 100% rename from service/configservice.php rename to lib/Service/ConfigService.php diff --git a/lib/Util.php b/lib/Util.php new file mode 100644 index 0000000..e9b35a4 --- /dev/null +++ b/lib/Util.php @@ -0,0 +1,61 @@ + + * + * @author Julius Härtl + * + * @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 . + * + */ + +namespace OCA\AppOrder; + +use OCA\AppOrder\Service\ConfigService; + +class Util { + + private $userId; + private $appConfig; + + public function __construct(ConfigService $appConfig, $userId) { + $this->userId = $userId; + $this->appConfig = $appConfig; + } + public function getAppOrder() { + $order_user = $this->appConfig->getUserValue('order', $this->userId); + $order_default = $this->appConfig->getAppValue('order'); + if ($order_user !== null && $order_user !== "") + $order = $order_user; + else + $order = $order_default; + return $order; + } + + public function matchOrder($nav, $order) { + $nav_tmp = array(); + $result = array(); + foreach ($nav as $app) + $nav_tmp[$app['href']] = $app; + foreach ($order as $app) + if(array_key_exists($app, $nav_tmp)) + $result[$app] = $nav_tmp[$app]; + foreach ($nav as $app) + if (!array_key_exists($app['href'], $result)) + $result[$app['href']] = $app; + return $result; + } + +} \ No newline at end of file diff --git a/tests/integration/AppTest.php b/tests/Integration/AppTest.php similarity index 100% rename from tests/integration/AppTest.php rename to tests/Integration/AppTest.php diff --git a/tests/bootstrap.php b/tests/bootstrap.php index 2249de2..ad27814 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,16 +1,36 @@ * - * This file is licensed under the Affero General Public License version 3 or - * later. See the COPYING file. + * @author Julius Härtl + * + * @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 . * - * @author jus - * @copyright jus 2016 */ -require_once __DIR__.'/../../../tests/bootstrap.php'; -require_once __DIR__.'/../appinfo/autoload.php'; +require_once __DIR__ . '/../../../tests/bootstrap.php'; +require_once __DIR__ . '/../appinfo/autoload.php'; + + +require_once __DIR__.'/../../../lib/base.php'; +if(!class_exists('PHPUnit_Framework_TestCase')) { + require_once('PHPUnit/Autoload.php'); +} -\OC::$loader->addValidRoot(OC::$SERVERROOT.'/tests'); \OC_App::loadApp('apporder'); + +OC_Hook::clear(); + diff --git a/tests/unit/UtilTest.php b/tests/unit/UtilTest.php new file mode 100644 index 0000000..123386b --- /dev/null +++ b/tests/unit/UtilTest.php @@ -0,0 +1,99 @@ + + * + * @author Julius Härtl + * + * @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 . + * + */ + +namespace OCA\AppOrder; + +use OCA\AppOrder\Service\ConfigService; +use \OCA\AppOrder\Util; + +class UtilTest extends \PHPUnit_Framework_TestCase { + + /** + * @var ConfigService + */ + private $service; + private $userId; + private $util; + private $config; + public function setUp() { + + parent::setUp(); + + $this->config = $this->getMockBuilder('OCP\IConfig') + ->disableOriginalConstructor() + ->getMock(); + $this->service = $this->getMockBuilder('\OCA\AppOrder\Service\ConfigService') + ->disableOriginalConstructor() + ->getMock(); + $this->userId = 'admin'; + $this->util = new Util($this->service, $this->userId); + + } + + public function testMatchOrder() { + $nav = [ + ['href' => '/app/files/', 'name' => 'Files'], + ['href' => '/app/calendar/', 'name' => 'Calendar'], + ['href' => '/app/tasks/', 'name' => 'Tasks'], + ]; + $order = ['/app/calendar/', '/app/tasks/']; + $result = $this->util->matchOrder($nav, $order); + $expected = [ + '/app/calendar/' => ['href' => '/app/calendar/', 'name' => 'Calendar'], + '/app/tasks/' => ['href' => '/app/tasks/', 'name' => 'Tasks'], + '/app/files/' => ['href' => '/app/files/', 'name' => 'Files'], + ]; + $this->assertEquals($expected, $result); + } + + public function testGetAppOrder() { + $nav_system = ['/app/calendar/', '/app/tasks/']; + $nav_user = ['/app/files/', '/app/calendar/', '/app/tasks/']; + $this->service->expects($this->once()) + ->method('getAppValue') + ->with('order') + ->will($this->returnValue(json_encode($nav_system))); + $this->service->expects($this->once()) + ->method('getUserValue') + ->with('order', $this->userId) + ->will($this->returnValue(json_encode($nav_user))); + $result = $this->util->getAppOrder(); + $this->assertEquals(json_encode($nav_user), $result); + } + + public function testGetAppOrderNoUser() { + $nav_system = ['/app/calendar/', '/app/tasks/']; + $nav_user = ''; + $this->service->expects($this->once()) + ->method('getAppValue') + ->with('order') + ->will($this->returnValue(json_encode($nav_system))); + $this->service->expects($this->once()) + ->method('getUserValue') + ->with('order', $this->userId) + ->will($this->returnValue($nav_user)); + $result = $this->util->getAppOrder(); + $this->assertEquals(json_encode($nav_system), $result); + } + +} diff --git a/tests/unit/controller/AppControllerTest.php b/tests/unit/controller/AppControllerTest.php new file mode 100644 index 0000000..e2281d7 --- /dev/null +++ b/tests/unit/controller/AppControllerTest.php @@ -0,0 +1,98 @@ + + * + * @author Julius Härtl + * + * @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 . + * + */ + +namespace OCA\AppOrder\Tests\Unit\Controller; + +use OCP\IRequest; +use OCP\AppFramework\Http\DataResponse; +use OCP\AppFramework\Http; +use \OCA\AppOrder\Service; +use \OCA\AppOrder\AppInfo\Application; +use \OCA\AppOrder\Controller; +use OCA\AppOrder\Controller\AppController; + +class AppControllerTest extends \Test\TestCase { + + private $container; + private $request; + private $service; + private $urlGenerator; + private $userId; + private $appName; + /** + * @var AppController + */ + private $controller; + private $config; + private $util; + + public function setUp() { + + parent::setUp(); + + $app = new \OCA\AppOrder\AppInfo\Application(); + $this->container = $app->getContainer(); + $this->request = $this->getMockBuilder('OCP\IRequest') + ->disableOriginalConstructor() + ->getMock(); + $this->config = $this->getMockBuilder('OCP\IConfig') + ->disableOriginalConstructor() + ->getMock(); + $this->service = $this->getMockBuilder('\OCA\AppOrder\Service\ConfigService') + ->disableOriginalConstructor() + ->getMock(); + $this->urlGenerator = \OC::$server->getURLGenerator(); + $this->util = $this->getMockBuilder('\OCA\AppOrder\Util')->disableOriginalConstructor()->getMock(); + + $this->userId = 'admin'; + $this->appName = 'apporder'; + $this->controller = new AppController( + $this->appName, $this->request, $this->service, $this->urlGenerator, $this->util, + $this->userId + ); + + } + + public function testIndex() { + $this->util->expects($this->once()) + ->method('getAppOrder') + ->willReturn( + json_encode(['/index.php/foo/bar', '/index.php/bar/foo']) + ); + $expected = new Http\RedirectResponse('/index.php/foo/bar'); + $result = $this->controller->index(); + $this->assertEquals($expected, $result); + } + + public function testIndexEmpty() { + $this->util->expects($this->once()) + ->method('getAppOrder') + ->willReturn(""); + $result = $this->controller->index(); + + $expected = new Http\RedirectResponse('http://localhost/index.php/apps/files/'); + $this->assertEquals($expected, $result); + } + + +} diff --git a/tests/unit/controller/SettingsControllerTest.php b/tests/unit/controller/SettingsControllerTest.php index 5550f19..65ba926 100644 --- a/tests/unit/controller/SettingsControllerTest.php +++ b/tests/unit/controller/SettingsControllerTest.php @@ -23,7 +23,7 @@ public function setUp() { parent::setUp(); - $app = new Application(); + $app = new \OCA\AppOrder\AppInfo\Application(); $this->container = $app->getContainer(); $this->request = $this->getMockBuilder('OCP\IRequest') ->disableOriginalConstructor() @@ -37,10 +37,12 @@ public function setUp() { $this->navigationManager = $this->getMockBuilder('\OCP\INavigationManager')->setMethods(['getAll', 'add', 'setActiveEntry']) ->disableOriginalConstructor() ->getMock(); + $this->userId = 'admin'; $this->appName = 'apporder'; + $this->util = new \OCA\AppOrder\Util($this->service, $this->userId); $this->controller = new \OCA\AppOrder\Controller\SettingsController( - $this->appName, $this->request, $this->service, $this->navigationManager, + $this->appName, $this->request, $this->service, $this->navigationManager, $this->util, $this->userId ); @@ -74,50 +76,6 @@ public function testAdminIndex() { $this->assertEquals($expected, $result); } - public function testMatchOrder() { - $nav = [ - ['href' => '/app/files/', 'name' => 'Files'], - ['href' => '/app/calendar/', 'name' => 'Calendar'], - ['href' => '/app/tasks/', 'name' => 'Tasks'], - ]; - $order = ['/app/calendar/', '/app/tasks/']; - $result = $this->controller->matchOrder($nav, $order); - $expected = [ - '/app/calendar/' => ['href' => '/app/calendar/', 'name' => 'Calendar'], - '/app/tasks/' => ['href' => '/app/tasks/', 'name' => 'Tasks'], - '/app/files/' => ['href' => '/app/files/', 'name' => 'Files'], - ]; - $this->assertEquals($expected, $result); - } - - public function testGetAppOrder() { - $nav_system = ['/app/calendar/', '/app/tasks/']; - $nav_user = ['/app/files/', '/app/calendar/', '/app/tasks/']; - $this->service->expects($this->once()) - ->method('getAppValue') - ->with('order') - ->will($this->returnValue(json_encode($nav_system))); - $this->service->expects($this->once()) - ->method('getUserValue') - ->with('order', $this->userId) - ->will($this->returnValue(json_encode($nav_user))); - $result = $this->controller->getAppOrder(); - $this->assertEquals(json_encode($nav_user), $result); - } - public function testGetAppOrderNoUser() { - $nav_system = ['/app/calendar/', '/app/tasks/']; - $nav_user = ''; - $this->service->expects($this->once()) - ->method('getAppValue') - ->with('order') - ->will($this->returnValue(json_encode($nav_system))); - $this->service->expects($this->once()) - ->method('getUserValue') - ->with('order', $this->userId) - ->will($this->returnValue($nav_user)); - $result = $this->controller->getAppOrder(); - $this->assertEquals(json_encode($nav_system), $result); - } public function testGetOrder() { $nav_system = ['/app/calendar/', '/app/tasks/'];