From fbad651ebd31d09406ef141e61ea396ad1eda710 Mon Sep 17 00:00:00 2001 From: Bernhard Posselt Date: Tue, 21 Oct 2014 15:14:19 +0200 Subject: Make config.ini editable in the admin interface --- CHANGELOG.md | 3 + appinfo/app.json | 1 + appinfo/app.php | 5 +- appinfo/application.php | 17 +++- appinfo/preupdate.php | 0 appinfo/routes.php | 3 + config/appconfig.php | 26 ++++- config/schema.json | 3 + controller/admincontroller.php | 76 +++++++++++++++ css/admin.css | 8 ++ js/Gruntfile.js | 4 +- js/admin/Admin.js | 83 ++++++++++++++++ templates/admin.php | 76 +++++++++++++++ tests/unit/controller/AdminControllerTest.php | 133 ++++++++++++++++++++++++++ 14 files changed, 429 insertions(+), 9 deletions(-) create mode 100644 appinfo/preupdate.php create mode 100644 controller/admincontroller.php create mode 100644 css/admin.css create mode 100644 js/admin/Admin.js create mode 100644 templates/admin.php create mode 100644 tests/unit/controller/AdminControllerTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 80da0e219..cd820ccd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +owncloud-news (3.406) +* **Enhancement**: Make config.ini editable in the admin interface + owncloud-news (3.405) * **Bugfix**: Fix mobile view for ownCloud 7 * **Enhancement**: Add shortcuts for jumping to next/previous folder diff --git a/appinfo/app.json b/appinfo/app.json index 5e110c8a9..6d8ed231d 100644 --- a/appinfo/app.json +++ b/appinfo/app.json @@ -34,6 +34,7 @@ "hooks": { "OC_User::pre_deleteUser": "OCA\\News\\Hooks\\User::deleteUser" }, + "admin": true, "categories": ["Multimedia"], "dependencies": { "databases": ["pgsql", "sqlite3", "mysql"], diff --git a/appinfo/app.php b/appinfo/app.php index a6de66ce2..8188d3eeb 100644 --- a/appinfo/app.php +++ b/appinfo/app.php @@ -26,6 +26,5 @@ set_error_handler(function ($code, $message) { $container = new Application(); $config = $container->getAppConfig(); -$config->registerNavigation(); -$config->registerBackgroundJobs(); -$config->registerHooks(); \ No newline at end of file +$config->registerAll(); +$config->testDependencies(); \ No newline at end of file diff --git a/appinfo/application.php b/appinfo/application.php index cdbaa82d6..e410ce701 100644 --- a/appinfo/application.php +++ b/appinfo/application.php @@ -21,6 +21,7 @@ use \OCP\User; use \OCA\News\Config\AppConfig; use \OCA\News\Config\Config; +use \OCA\News\Controller\AdminController; use \OCA\News\Controller\PageController; use \OCA\News\Controller\FolderController; use \OCA\News\Controller\FeedController; @@ -92,6 +93,15 @@ class Application extends App { ); }); + $container->registerService('AdminController', function($c) { + return new AdminController( + $c->query('AppName'), + $c->query('Request'), + $c->query('Config'), + $c->query('ConfigPath') + ); + }); + $container->registerService('FolderController', function($c) { return new FolderController( $c->query('AppName'), @@ -329,13 +339,17 @@ class Application extends App { return $view; }); + $container->registerService('ConfigPath', function() { + return 'config.ini'; + }); + $container->registerService('Config', function($c) { $config = new Config( $c->query('ConfigView'), $c->query('Logger'), $c->query('LoggerParameters') ); - $config->read('config.ini', true); + $config->read($c->query('ConfigPath'), true); return $config; }); @@ -470,6 +484,5 @@ class Application extends App { } - public function dispatchPart($controller, $) } diff --git a/appinfo/preupdate.php b/appinfo/preupdate.php new file mode 100644 index 000000000..e69de29bb diff --git a/appinfo/routes.php b/appinfo/routes.php index 7703de1c7..930fdb136 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -23,6 +23,9 @@ $application->registerRoutes($this, ['routes' => [ ['name' => 'page#update_settings', 'url' => '/settings', 'verb' => 'PUT'], ['name' => 'page#manifest', 'url' => '/manifest.webapp', 'verb' => 'GET'], + // admin + ['name' => 'admin#update', 'url' => '/admin', 'verb' => 'PUT'], + // folders ['name' => 'folder#index', 'url' => '/folders', 'verb' => 'GET'], ['name' => 'folder#create', 'url' => '/folders', 'verb' => 'POST'], diff --git a/config/appconfig.php b/config/appconfig.php index 89c02a1de..e738b22cd 100644 --- a/config/appconfig.php +++ b/config/appconfig.php @@ -13,11 +13,11 @@ namespace OCA\News\Config; -use OCP\INavigationManager; -use OCP\IURLGenerator; +use \OCP\INavigationManager; +use \OCP\IURLGenerator; use \OCP\Backgroundjob; use \OCP\Util; - +use \OCP\App; // Used to parse app.json file, should be in core at some point class AppConfig { @@ -97,6 +97,17 @@ class AppConfig { } + /** + * Registers all config options + */ + public function registerAll() { + $this->registerNavigation(); + $this->registerBackgroundJobs(); + $this->registerHooks(); + $this->registerAdmin(); + } + + /** * Parses the navigation and creates a navigation entry if needed */ @@ -120,6 +131,15 @@ class AppConfig { } + /** + * Registers admin pages + */ + public function registerAdmin() { + if ($this->config['admin']) { + App::registerAdmin($this->config['id'], 'admin/admin'); + } + } + /** * Registers all jobs in the config diff --git a/config/schema.json b/config/schema.json index 7e44878c9..c65a1c8dd 100644 --- a/config/schema.json +++ b/config/schema.json @@ -16,6 +16,9 @@ "type": "string", "enum": ["AGPL", "MIT", "GPL", "LGPL", "BSD","Apache"] }, + "admin": { + "type": "boolean" + }, "version": { "type": "string", "pattern": "^[0-9]+(\\.[0-9]+)*$" diff --git a/controller/admincontroller.php b/controller/admincontroller.php new file mode 100644 index 000000000..2b876c394 --- /dev/null +++ b/controller/admincontroller.php @@ -0,0 +1,76 @@ + + * @author Bernhard Posselt + * @copyright Alessandro Cosentino 2012 + * @copyright Bernhard Posselt 2012, 2014 + */ + +namespace OCA\News\Controller; + +use \OCP\AppFramework\Http\TemplateResponse; +use \OCP\IRequest; +use \OCP\AppFramework\Controller; + +use \OCA\News\Config\Config; + +class AdminController extends Controller { + + private $config; + private $configPath; + + public function __construct($appName, IRequest $request, Config $config, + $configPath){ + parent::__construct($appName, $request); + $this->config = $config; + $this->configPath = $configPath; + } + + // There are no checks for the index method since the output is rendered + // in admin/admin.php + public function index() { + $data = [ + 'autoPurgeMinimumInterval' => $this->config->getAutoPurgeMinimumInterval(), + 'autoPurgeCount' => $this->config->getAutoPurgeCount(), + 'cacheDuration' => $this->config->getSimplePieCacheDuration(), + 'feedFetcherTimeout' => $this->config->getFeedFetcherTimeout(), + 'useCronUpdates' => $this->config->getUseCronUpdates(), + ]; + return new TemplateResponse($this->appName, 'admin', $data, 'blank'); + } + + + /** + * @param int $autoPurgeMinimumInterval + * @param int $autoPurgeCount + * @param int $cacheDuration + * @param int $feedFetcherTimeout + * @param bool $useCronUpdates + * @return array with the updated values + */ + public function update($autoPurgeMinimumInterval, $autoPurgeCount, + $cacheDuration, $feedFetcherTimeout, + $useCronUpdates) { + $this->config->setAutoPurgeMinimumInterval($autoPurgeMinimumInterval); + $this->config->setAutoPurgeCount($autoPurgeCount); + $this->config->setSimplePieCacheDuration($cacheDuration); + $this->config->setFeedFetcherTimeout($feedFetcherTimeout); + $this->config->setUseCronUpdates($useCronUpdates); + $this->config->write($this->configPath); + + return [ + 'autoPurgeMinimumInterval' => $this->config->getAutoPurgeMinimumInterval(), + 'autoPurgeCount' => $this->config->getAutoPurgeCount(), + 'cacheDuration' => $this->config->getSimplePieCacheDuration(), + 'feedFetcherTimeout' => $this->config->getFeedFetcherTimeout(), + 'useCronUpdates' => $this->config->getUseCronUpdates(), + ]; + } + + +} \ No newline at end of file diff --git a/css/admin.css b/css/admin.css new file mode 100644 index 000000000..8571bc860 --- /dev/null +++ b/css/admin.css @@ -0,0 +1,8 @@ +#news-saved-message { + margin: 15px 0; + display: none; +} + +#news .form-line { + margin: 25px 0 15px 0; +} \ No newline at end of file diff --git a/js/Gruntfile.js b/js/Gruntfile.js index d690464a1..a46388298 100644 --- a/js/Gruntfile.js +++ b/js/Gruntfile.js @@ -118,7 +118,8 @@ module.exports = function (grunt) { 'controller/**/*.js', 'directive/**/*.js', 'tests/**/*.js', - 'gui/**/*.js' + 'gui/**/*.js', + 'admin/**/*.js' ] }, options: { @@ -130,6 +131,7 @@ module.exports = function (grunt) { files: [ '../css/*.css', '!../css/*.min.css', + 'admin/**/*.js', 'tests/**/*.js', 'app/**/*.js', 'controller/**/*.js', diff --git a/js/admin/Admin.js b/js/admin/Admin.js new file mode 100644 index 000000000..61af46461 --- /dev/null +++ b/js/admin/Admin.js @@ -0,0 +1,83 @@ +/** + * ownCloud - News + * + * This file is licensed under the Affero General Public License version 3 or + * later. See the COPYING file. + * + * @author Bernhard Posselt + * @copyright Bernhard Posselt 2014 + */ + +/** + * Used to update the admin settings + */ +(function (window, document, $) { + 'use strict'; + + $(document).ready(function () { + var useCronUpdatesInput = + $('#news input[name="news-use-cron-updates"]'); + var autoPurgeMinimumIntervalInput = + $('#news input[name="news-auto-purge-minimum-interval"]'); + var autoPurgeCountInput = + $('#news input[name="news-auto-purge-count"]'); + var cacheDurationInput = + $('#news input[name="news-cache-duration"]'); + var feedFetcherTimeoutInput = + $('#news input[name="news-feed-fetcher-timeout"]'); + var savedMessage = $('#news-saved-message'); + + var saved = function () { + if (savedMessage.is(':visible')) { + savedMessage.hide(); + } + + savedMessage.fadeIn(function () { + setTimeout(function () { + savedMessage.fadeOut(); + }, 5000); + }); + }; + + var submit = function () { + var autoPurgeMinimumInterval = autoPurgeMinimumIntervalInput.val(); + var autoPurgeCount = autoPurgeCountInput.val(); + var cacheDuration = cacheDurationInput.val(); + var feedFetcherTimeout = feedFetcherTimeoutInput.val(); + var useCronUpdates = useCronUpdatesInput.is(':checked'); + + var data = { + autoPurgeMinimumInterval: + parseInt(autoPurgeMinimumInterval, 10), + autoPurgeCount: parseInt(autoPurgeCount, 10), + cacheDuration: parseInt(cacheDuration, 10), + feedFetcherTimeout: parseInt(feedFetcherTimeout, 10), + useCronUpdates: useCronUpdates + }; + + var url = OC.generateUrl('/apps/news/admin'); + + $.ajax({ + type: 'PUT', + contentType: 'application/json; charset=utf-8', + url: url, + data: JSON.stringify(data), + dataType: 'json' + }).success(function (data) { + saved(); + autoPurgeMinimumIntervalInput + .val(data.autoPurgeMinimumInterval); + autoPurgeCountInput.val(data.autoPurgeCount); + cacheDurationInput.val(data.cacheDuration); + feedFetcherTimeoutInput.val(data.feedFetcherTimeout); + useCronUpdatesInput.prop('checked', data.useCronUpdates); + }); + + } + + $('#news input[type="text"]').blur(submit); + $('#news input[type="checkbox"]').change(submit); + }); + + +}(window, document, jQuery)); \ No newline at end of file diff --git a/templates/admin.php b/templates/admin.php new file mode 100644 index 000000000..eb5960149 --- /dev/null +++ b/templates/admin.php @@ -0,0 +1,76 @@ + + +
+

News

+
+ > + +

+ t( + 'Disable this if you run a custom updater such as the Python' . + 'updater included in the app.' + )); ?> +

+
+
+ + +

+ + t( + 'Minimum amount of seconds after deleted feeds and folders are ' . + 'removed from the database. Values below 60 seconds are ignored' + )); ?> +

+
+
+ + +

+ + t( + 'Defines the minimum amount of articles that can be unread per ' . + 'feed before they get deleted.' + )); ?> +

+
+
+ + +

+ t('Amount of seconds to cache feeds')); ?> +

+
+
+ + +

+ + t( + 'Maximum number of seconds to wait for an RSS or Atom feed to ' . + 'load. If a feed takes longer than that number of seconds to ' . + 'update, the update will be aborted.' + )); ?> +

+
+
+ t('Saved')); ?> +
+
\ No newline at end of file diff --git a/tests/unit/controller/AdminControllerTest.php b/tests/unit/controller/AdminControllerTest.php new file mode 100644 index 000000000..61e510c24 --- /dev/null +++ b/tests/unit/controller/AdminControllerTest.php @@ -0,0 +1,133 @@ + + * @author Bernhard Posselt + * @copyright Alessandro Cosentino 2012 + * @copyright Bernhard Posselt 2012, 2014 + */ + +namespace OCA\News\Controller; + + +class AdminControllerTest extends \PHPUnit_Framework_TestCase { + + private $appName; + private $request; + private $controller; + private $config; + private $configPath; + + /** + * Gets run before each test + */ + public function setUp(){ + $this->appName = 'news'; + $this->request = $this->getMockBuilder( + '\OCP\IRequest') + ->disableOriginalConstructor() + ->getMock(); + $this->config = $this->getMockBuilder( + '\OCA\News\Config\Config') + ->disableOriginalConstructor() + ->getMock(); + $this->configPath = 'my.ini'; + $this->controller = new AdminController($this->appName, $this->request, + $this->config, $this->configPath); + } + + + public function testIndex() { + $expected = [ + 'autoPurgeMinimumInterval' => 1, + 'autoPurgeCount' => 2, + 'cacheDuration' => 3, + 'feedFetcherTimeout' => 4, + 'useCronUpdates' => 5 + ]; + $this->config->expects($this->once()) + ->method('getAutoPurgeMinimumInterval') + ->will($this->returnValue($expected['autoPurgeMinimumInterval'])); + $this->config->expects($this->once()) + ->method('getAutoPurgeCount') + ->will($this->returnValue($expected['autoPurgeCount'])); + $this->config->expects($this->once()) + ->method('getSimplePieCacheDuration') + ->will($this->returnValue($expected['cacheDuration'])); + $this->config->expects($this->once()) + ->method('getFeedFetcherTimeout') + ->will($this->returnValue($expected['feedFetcherTimeout'])); + $this->config->expects($this->once()) + ->method('getUseCronUpdates') + ->will($this->returnValue($expected['useCronUpdates'])); + + $response = $this->controller->index(); + $data = $response->getParams(); + $name = $response->getTemplateName(); + $type = $response->getRenderAs(); + + $this->assertEquals($type, 'blank'); + $this->assertEquals($name, 'admin'); + $this->assertEquals($expected, $data); + } + + + public function testUpdate() { + $expected = [ + 'autoPurgeMinimumInterval' => 1, + 'autoPurgeCount' => 2, + 'cacheDuration' => 3, + 'feedFetcherTimeout' => 4, + 'useCronUpdates' => 5 + ]; + + $this->config->expects($this->once()) + ->method('setAutoPurgeMinimumInterval') + ->with($this->equalTo($expected['autoPurgeMinimumInterval'])); + $this->config->expects($this->once()) + ->method('setAutoPurgeCount') + ->with($this->equalTo($expected['autoPurgeCount'])); + $this->config->expects($this->once()) + ->method('setSimplePieCacheDuration') + ->with($this->equalTo($expected['cacheDuration'])); + $this->config->expects($this->once()) + ->method('setFeedFetcherTimeout') + ->with($this->equalTo($expected['feedFetcherTimeout'])); + $this->config->expects($this->once()) + ->method('setUseCronUpdates') + ->with($this->equalTo($expected['useCronUpdates'])); + $this->config->expects($this->once()) + ->method('write') + ->with($this->equalTo($this->configPath)); + + $this->config->expects($this->once()) + ->method('getAutoPurgeMinimumInterval') + ->will($this->returnValue($expected['autoPurgeMinimumInterval'])); + $this->config->expects($this->once()) + ->method('getAutoPurgeCount') + ->will($this->returnValue($expected['autoPurgeCount'])); + $this->config->expects($this->once()) + ->method('getSimplePieCacheDuration') + ->will($this->returnValue($expected['cacheDuration'])); + $this->config->expects($this->once()) + ->method('getFeedFetcherTimeout') + ->will($this->returnValue($expected['feedFetcherTimeout'])); + $this->config->expects($this->once()) + ->method('getUseCronUpdates') + ->will($this->returnValue($expected['useCronUpdates'])); + + $response = $this->controller->update( + $expected['autoPurgeMinimumInterval'], + $expected['autoPurgeCount'], + $expected['cacheDuration'], + $expected['feedFetcherTimeout'], + $expected['useCronUpdates'] + ); + + $this->assertEquals($expected, $response); + } +} \ No newline at end of file -- cgit v1.2.3