From 643fa4624dd7ba2db1349f16131bf330aeee3387 Mon Sep 17 00:00:00 2001 From: Bernhard Posselt Date: Wed, 9 Apr 2014 16:10:48 +0200 Subject: port to internal controller, some routes are still broken --- api/feedapi.php | 236 ------- api/folderapi.php | 170 ----- api/itemapi.php | 276 --------- api/newsapi.php | 106 ---- app/news.php | 381 ++++++++++++ appinfo/routes.php | 489 +++------------ articleenhancer/xpatharticleenhancer.php | 7 +- businesslayer/feedbusinesslayer.php | 9 +- businesslayer/folderbusinesslayer.php | 8 +- businesslayer/itembusinesslayer.php | 6 +- controller/apicontroller.php | 106 ++++ controller/feedapicontroller.php | 236 +++++++ controller/feedcontroller.php | 4 +- controller/folderapicontroller.php | 170 +++++ controller/foldercontroller.php | 2 +- controller/itemapicontroller.php | 276 +++++++++ controller/itemcontroller.php | 2 +- dependencyinjection/dicontainer.php | 367 ----------- fetcher/feedfetcher.php | 15 +- js/public/app.js | 2 - tests/unit/api/FeedAPITest.php | 546 ---------------- tests/unit/api/FolderAPITest.php | 440 ------------- tests/unit/api/ItemAPITest.php | 689 --------------------- tests/unit/api/NewsAPITest.php | 142 ----- .../articleenhancer/XPathArticleEnhancerTest.php | 11 +- tests/unit/businesslayer/FeedBusinessLayerTest.php | 15 +- .../unit/businesslayer/FolderBusinessLayerTest.php | 14 +- tests/unit/businesslayer/ItemBusinessLayerTest.php | 14 +- tests/unit/controller/ApiControllerTest.php | 142 +++++ tests/unit/controller/FeedApiControllerTest.php | 546 ++++++++++++++++ tests/unit/controller/FeedControllerTest.php | 20 +- tests/unit/controller/FolderApiControllerTest.php | 440 +++++++++++++ tests/unit/controller/FolderControllerTest.php | 6 +- tests/unit/controller/ItemApiControllerTest.php | 689 +++++++++++++++++++++ tests/unit/controller/ItemControllerTest.php | 10 +- tests/unit/fetcher/FeedFetcherTest.php | 18 +- utility/timefactory.php | 42 -- 37 files changed, 3167 insertions(+), 3485 deletions(-) delete mode 100644 api/feedapi.php delete mode 100644 api/folderapi.php delete mode 100644 api/itemapi.php delete mode 100644 api/newsapi.php create mode 100644 app/news.php create mode 100644 controller/apicontroller.php create mode 100644 controller/feedapicontroller.php create mode 100644 controller/folderapicontroller.php create mode 100644 controller/itemapicontroller.php delete mode 100644 dependencyinjection/dicontainer.php delete mode 100644 tests/unit/api/FeedAPITest.php delete mode 100644 tests/unit/api/FolderAPITest.php delete mode 100644 tests/unit/api/ItemAPITest.php delete mode 100644 tests/unit/api/NewsAPITest.php create mode 100644 tests/unit/controller/ApiControllerTest.php create mode 100644 tests/unit/controller/FeedApiControllerTest.php create mode 100644 tests/unit/controller/FolderApiControllerTest.php create mode 100644 tests/unit/controller/ItemApiControllerTest.php delete mode 100644 utility/timefactory.php diff --git a/api/feedapi.php b/api/feedapi.php deleted file mode 100644 index 0d9d158f1..000000000 --- a/api/feedapi.php +++ /dev/null @@ -1,236 +0,0 @@ -. -* -*/ - -namespace OCA\News\API; - -use \OCP\IRequest; -use \OCP\AppFramework\Controller; -use \OCP\AppFramework\Http; -use \OCP\AppFramework\Http\JSONResponse; - -use \OCA\News\Core\API; -use \OCA\News\BusinessLayer\FeedBusinessLayer; -use \OCA\News\BusinessLayer\FolderBusinessLayer; -use \OCA\News\BusinessLayer\ItemBusinessLayer; -use \OCA\News\BusinessLayer\BusinessLayerException; -use \OCA\News\BusinessLayer\BusinessLayerConflictException; - - -class FeedAPI extends Controller { - - private $itemBusinessLayer; - private $feedBusinessLayer; - private $folderBusinessLayer; - private $api; - - public function __construct(API $api, - IRequest $request, - FolderBusinessLayer $folderBusinessLayer, - FeedBusinessLayer $feedBusinessLayer, - ItemBusinessLayer $itemBusinessLayer){ - parent::__construct($api->getAppName(), $request); - $this->folderBusinessLayer = $folderBusinessLayer; - $this->feedBusinessLayer = $feedBusinessLayer; - $this->itemBusinessLayer = $itemBusinessLayer; - $this->api = $api; - } - - - /** - * @NoAdminRequired - * @NoCSRFRequired - * @API - */ - public function getAll() { - $userId = $this->api->getUserId(); - - $result = array( - 'feeds' => array(), - 'starredCount' => $this->itemBusinessLayer->starredCount($userId) - ); - - foreach ($this->feedBusinessLayer->findAll($userId) as $feed) { - array_push($result['feeds'], $feed->toAPI()); - } - - // check case when there are no items - try { - $result['newestItemId'] = - $this->itemBusinessLayer->getNewestItemId($userId); - } catch(BusinessLayerException $ex) {} - - return new JSONResponse($result); - } - - - /** - * @NoAdminRequired - * @NoCSRFRequired - * @API - */ - public function create() { - $userId = $this->api->getUserId(); - $feedUrl = $this->params('url'); - $folderId = (int) $this->params('folderId', 0); - - try { - $this->feedBusinessLayer->purgeDeleted($userId, false); - - $feed = $this->feedBusinessLayer->create($feedUrl, $folderId, $userId); - $result = array( - 'feeds' => array($feed->toAPI()) - ); - - try { - $result['newestItemId'] = - $this->itemBusinessLayer->getNewestItemId($userId); - } catch(BusinessLayerException $ex) {} - - return new JSONResponse($result); - - } catch(BusinessLayerConflictException $ex) { - return new JSONResponse(array('message' => $ex->getMessage()), - Http::STATUS_CONFLICT); - } catch(BusinessLayerException $ex) { - return new JSONResponse(array('message' => $ex->getMessage()), - Http::STATUS_NOT_FOUND); - } - } - - - /** - * @NoAdminRequired - * @NoCSRFRequired - * @API - */ - public function delete() { - $userId = $this->api->getUserId(); - $feedId = (int) $this->params('feedId'); - - try { - $this->feedBusinessLayer->delete($feedId, $userId); - return new JSONResponse(); - } catch(BusinessLayerException $ex) { - return new JSONResponse(array('message' => $ex->getMessage()), - Http::STATUS_NOT_FOUND); - } - } - - - /** - * @NoAdminRequired - * @NoCSRFRequired - * @API - */ - public function read() { - $userId = $this->api->getUserId(); - $feedId = (int) $this->params('feedId'); - $newestItemId = (int) $this->params('newestItemId'); - - $this->itemBusinessLayer->readFeed($feedId, $newestItemId, $userId); - return new JSONResponse(); - } - - - /** - * @NoAdminRequired - * @NoCSRFRequired - * @API - */ - public function move() { - $userId = $this->api->getUserId(); - $feedId = (int) $this->params('feedId'); - $folderId = (int) $this->params('folderId'); - - try { - $this->feedBusinessLayer->move($feedId, $folderId, $userId); - return new JSONResponse(); - } catch(BusinessLayerException $ex) { - return new JSONResponse(array('message' => $ex->getMessage()), - Http::STATUS_NOT_FOUND); - } - } - - - /** - * @NoAdminRequired - * @NoCSRFRequired - * @API - */ - public function rename() { - $userId = $this->api->getUserId(); - $feedId = (int) $this->params('feedId'); - $feedTitle = $this->params('feedTitle'); - - try { - $this->feedBusinessLayer->rename($feedId, $feedTitle, $userId); - return new JSONResponse(); - } catch(BusinessLayerException $ex) { - return new JSONResponse(array('message' => $ex->getMessage()), - Http::STATUS_NOT_FOUND); - } - } - - - /** - * @NoCSRFRequired - * @API - */ - public function getAllFromAllUsers() { - $feeds = $this->feedBusinessLayer->findAllFromAllUsers(); - $result = array('feeds' => array()); - - foreach ($feeds as $feed) { - array_push($result['feeds'], array( - 'id' => $feed->getId(), - 'userId' => $feed->getUserId() - )); - } - - return new JSONResponse($result); - } - - - /** - * @NoCSRFRequired - * @API - */ - public function update() { - $userId = $this->params('userId'); - $feedId = (int) $this->params('feedId'); - - try { - $this->feedBusinessLayer->update($feedId, $userId); - // ignore update failure (feed could not be reachable etc, we dont care) - } catch(\Exception $ex) { - $this->api->log('Could not update feed ' . $ex->getMessage(), - 'debug'); - } - return new JSONResponse(); - - } - - -} diff --git a/api/folderapi.php b/api/folderapi.php deleted file mode 100644 index ba35462f5..000000000 --- a/api/folderapi.php +++ /dev/null @@ -1,170 +0,0 @@ -. -* -*/ - -namespace OCA\News\API; - -use \OCP\IRequest; -use \OCP\AppFramework\Controller; -use \OCP\AppFramework\Http; -use \OCP\AppFramework\Http\JSONResponse; - -use \OCA\News\Core\API; -use \OCA\News\BusinessLayer\FolderBusinessLayer; -use \OCA\News\BusinessLayer\ItemBusinessLayer; -use \OCA\News\BusinessLayer\BusinessLayerException; -use \OCA\News\BusinessLayer\BusinessLayerConflictException; -use \OCA\News\BusinessLayer\BusinessLayerValidationException; - - -class FolderAPI extends Controller { - - private $folderBusinessLayer; - private $itemBusinessLayer; - private $api; - - public function __construct(API $api, - IRequest $request, - FolderBusinessLayer $folderBusinessLayer, - ItemBusinessLayer $itemBusinessLayer){ - parent::__construct($api->getAppName(), $request); - $this->folderBusinessLayer = $folderBusinessLayer; - $this->itemBusinessLayer = $itemBusinessLayer; - $this->api = $api; - } - - - /** - * @NoAdminRequired - * @NoCSRFRequired - * @API - */ - public function getAll() { - $userId = $this->api->getUserId(); - $result = array( - 'folders' => array() - ); - - foreach ($this->folderBusinessLayer->findAll($userId) as $folder) { - array_push($result['folders'], $folder->toAPI()); - } - - return new JSONResponse($result); - } - - - /** - * @NoAdminRequired - * @NoCSRFRequired - * @API - */ - public function create() { - $userId = $this->api->getUserId(); - $folderName = $this->params('name'); - $result = array( - 'folders' => array() - ); - - try { - $this->folderBusinessLayer->purgeDeleted($userId, false); - $folder = $this->folderBusinessLayer->create($folderName, $userId); - array_push($result['folders'], $folder->toAPI()); - - return new JSONResponse($result); - - } catch(BusinessLayerValidationException $ex) { - return new JSONResponse(array('message' => $ex->getMessage()), - Http::STATUS_UNPROCESSABLE_ENTITY); - - } catch(BusinessLayerConflictException $ex) { - return new JSONResponse(array('message' => $ex->getMessage()), - Http::STATUS_CONFLICT); - } - } - - - /** - * @NoAdminRequired - * @NoCSRFRequired - * @API - */ - public function delete() { - $userId = $this->api->getUserId(); - $folderId = (int) $this->params('folderId'); - - try { - $this->folderBusinessLayer->delete($folderId, $userId); - return new JSONResponse(); - } catch(BusinessLayerException $ex) { - return new JSONResponse(array('message' => $ex->getMessage()), - Http::STATUS_NOT_FOUND); - } - } - - - /** - * @NoAdminRequired - * @NoCSRFRequired - * @API - */ - public function update() { - $userId = $this->api->getUserId(); - $folderId = (int) $this->params('folderId'); - $folderName = $this->params('name'); - - try { - $this->folderBusinessLayer->rename($folderId, $folderName, $userId); - return new JSONResponse(); - - } catch(BusinessLayerValidationException $ex) { - return new JSONResponse(array('message' => $ex->getMessage()), - Http::STATUS_UNPROCESSABLE_ENTITY); - - } catch(BusinessLayerConflictException $ex) { - return new JSONResponse(array('message' => $ex->getMessage()), - Http::STATUS_CONFLICT); - - } catch(BusinessLayerException $ex) { - return new JSONResponse(array('message' => $ex->getMessage()), - Http::STATUS_NOT_FOUND); - } - } - - - /** - * @NoAdminRequired - * @NoCSRFRequired - * @API - */ - public function read() { - $userId = $this->api->getUserId(); - $folderId = (int) $this->params('folderId'); - $newestItemId = (int) $this->params('newestItemId'); - - $this->itemBusinessLayer->readFolder($folderId, $newestItemId, $userId); - return new JSONResponse(); - } - - -} diff --git a/api/itemapi.php b/api/itemapi.php deleted file mode 100644 index c21b5817f..000000000 --- a/api/itemapi.php +++ /dev/null @@ -1,276 +0,0 @@ -. -* -*/ - -namespace OCA\News\API; - -use \OCP\IRequest; -use \OCP\AppFramework\Controller; -use \OCP\AppFramework\Http; -use \OCP\AppFramework\Http\JSONResponse; - -use \OCA\News\BusinessLayer\ItemBusinessLayer; -use \OCA\News\BusinessLayer\BusinessLayerException; -use \OCA\News\Core\API; - -class ItemAPI extends Controller { - - private $itemBusinessLayer; - private $api; - - public function __construct(API $api, - IRequest $request, - ItemBusinessLayer $itemBusinessLayer){ - parent::__construct($api->getAppName(), $request); - $this->itemBusinessLayer = $itemBusinessLayer; - $this->api = $api; - } - - - /** - * @NoAdminRequired - * @NoCSRFRequired - * @API - */ - public function getAll() { - $result = array( - 'items' => array() - ); - - $userId = $this->api->getUserId(); - $batchSize = (int) $this->params('batchSize', 20); - $offset = (int) $this->params('offset', 0); - $type = (int) $this->params('type'); - $id = (int) $this->params('id'); - $showAll = $this->params('getRead'); - - if($showAll === 'true' || $showAll === true) { - $showAll = true; - } else { - $showAll = false; - } - - $items = $this->itemBusinessLayer->findAll( - $id, - $type, - $batchSize, - $offset, - $showAll, - $userId - ); - - foreach ($items as $item) { - array_push($result['items'], $item->toAPI()); - } - - return new JSONResponse($result); - } - - - /** - * @NoAdminRequired - * @NoCSRFRequired - * @API - */ - public function getUpdated() { - $result = array( - 'items' => array() - ); - - $userId = $this->api->getUserId(); - $lastModified = (int) $this->params('lastModified', 0); - $type = (int) $this->params('type'); - $id = (int) $this->params('id'); - - $items = $this->itemBusinessLayer->findAllNew( - $id, - $type, - $lastModified, - true, - $userId - ); - - foreach ($items as $item) { - array_push($result['items'], $item->toAPI()); - } - - return new JSONResponse($result); - } - - - private function setRead($isRead) { - $userId = $this->api->getUserId(); - $itemId = (int) $this->params('itemId'); - try { - $this->itemBusinessLayer->read($itemId, $isRead, $userId); - return new JSONResponse(); - } catch(BusinessLayerException $ex){ - return new JSONResponse(array('message' => $ex->getMessage()), - Http::STATUS_NOT_FOUND); - } - } - - - private function setStarred($isStarred) { - $userId = $this->api->getUserId(); - $feedId = (int) $this->params('feedId'); - $guidHash = $this->params('guidHash'); - try { - $this->itemBusinessLayer->star($feedId, $guidHash, $isStarred, $userId); - return new JSONResponse(); - } catch(BusinessLayerException $ex){ - return new JSONResponse(array('message' => $ex->getMessage()), - Http::STATUS_NOT_FOUND); - } - } - - - /** - * @NoAdminRequired - * @NoCSRFRequired - * @API - */ - public function read() { - return $this->setRead(true); - } - - - /** - * @NoAdminRequired - * @NoCSRFRequired - * @API - */ - public function unread() { - return $this->setRead(false); - } - - - /** - * @NoAdminRequired - * @NoCSRFRequired - * @API - */ - public function star() { - return $this->setStarred(true); - } - - - /** - * @NoAdminRequired - * @NoCSRFRequired - * @API - */ - public function unstar() { - return $this->setStarred(false); - } - - - /** - * @NoAdminRequired - * @NoCSRFRequired - * @API - */ - public function readAll() { - $userId = $this->api->getUserId(); - $newestItemId = (int) $this->params('newestItemId'); - - $this->itemBusinessLayer->readAll($newestItemId, $userId); - return new JSONResponse(); - } - - - private function setMultipleRead($isRead) { - $userId = $this->api->getUserId(); - $items = $this->params('items'); - - foreach($items as $id) { - try { - $this->itemBusinessLayer->read($id, $isRead, $userId); - } catch(BusinessLayerException $ex) { - continue; - } - } - - return new JSONResponse(); - } - - - /** - * @NoAdminRequired - * @NoCSRFRequired - * @API - */ - public function readMultiple() { - return $this->setMultipleRead(true); - } - - - /** - * @NoAdminRequired - * @NoCSRFRequired - * @API - */ - public function unreadMultiple() { - return $this->setMultipleRead(false); - } - - - private function setMultipleStarred($isStarred) { - $userId = $this->api->getUserId(); - $items = $this->params('items'); - - foreach($items as $item) { - try { - $this->itemBusinessLayer->star($item['feedId'], - $item['guidHash'], $isStarred, $userId); - } catch(BusinessLayerException $ex) { - continue; - } - } - - return new JSONResponse(); - } - - - /** - * @NoAdminRequired - * @NoCSRFRequired - * @API - */ - public function starMultiple() { - return $this->setMultipleStarred(true); - } - - - /** - * @NoAdminRequired - * @NoCSRFRequired - * @API - */ - public function unstarMultiple() { - return $this->setMultipleStarred(false); - } - - -} diff --git a/api/newsapi.php b/api/newsapi.php deleted file mode 100644 index 151afedf3..000000000 --- a/api/newsapi.php +++ /dev/null @@ -1,106 +0,0 @@ -. -* -*/ - -namespace OCA\News\API; - -use \OCP\IRequest; -use \OCP\AppFramework\Controller; -use \OCP\AppFramework\Http; -use \OCP\AppFramework\Http\JSONResponse; -use \OCP\AppFramework\Http\Response; - -use \OCA\News\Utility\Updater; -use \OCA\News\Core\API; - -class NewsAPI extends Controller { - - private $updater; - private $api; - - public function __construct(API $api, IRequest $request, Updater $updater){ - parent::__construct($api->getAppName(), $request); - $this->updater = $updater; - $this->api = $api; - } - - - /** - * @NoAdminRequired - * @NoCSRFRequired - * @API - */ - public function version() { - $version = $this->api->getAppValue('installed_version'); - $response = new JSONResponse(array('version' => $version)); - return $response; - } - - - /** - * @NoCSRFRequired - * @API - */ - public function beforeUpdate() { - $this->updater->beforeUpdate(); - return new JSONResponse(); - } - - - /** - * @NoCSRFRequired - * @API - */ - public function afterUpdate() { - $this->updater->afterUpdate(); - return new JSONResponse(); - } - - - /** - * @NoAdminRequired - * @NoCSRFRequired - * @PublicPage - */ - public function cors() { - // needed for webapps access due to cross origin request policy - if(isset($this->request->server['HTTP_ORIGIN'])) { - $origin = $this->request->server['HTTP_ORIGIN']; - } else { - $origin = '*'; - } - - $response = new Response(); - $response->addHeader('Access-Control-Allow-Origin', $origin); - $response->addHeader('Access-Control-Allow-Methods', - 'PUT, POST, GET, DELETE'); - $response->addHeader('Access-Control-Allow-Credentials', 'true'); - $response->addHeader('Access-Control-Max-Age', '1728000'); - $response->addHeader('Access-Control-Allow-Headers', - 'Authorization, Content-Type'); - return $response; - } - - -} diff --git a/app/news.php b/app/news.php new file mode 100644 index 000000000..8b886f61d --- /dev/null +++ b/app/news.php @@ -0,0 +1,381 @@ +. +* +*/ + +namespace OCA\News\App; + +use \OC\Files\View; +use \OCP\AppFramework\App; + + +use \OCA\News\Core\API; + +use \OCA\News\Controller\PageController; +use \OCA\News\Controller\FolderController; +use \OCA\News\Controller\FeedController; +use \OCA\News\Controller\ItemController; +use \OCA\News\Controller\ExportController; +use \OCA\News\Controller\ApiController; +use \OCA\News\Controller\FolderApiController; +use \OCA\News\Controller\FeedApiController; +use \OCA\News\Controller\ItemApiController; + +use \OCA\News\BusinessLayer\FolderBusinessLayer; +use \OCA\News\BusinessLayer\FeedBusinessLayer; +use \OCA\News\BusinessLayer\ItemBusinessLayer; + +use \OCA\News\Db\FolderMapper; +use \OCA\News\Db\FeedMapper; +use \OCA\News\Db\ItemMapper; +use \OCA\News\Db\StatusFlag; +use \OCA\News\Db\MapperFactory; + +use \OCA\News\Utility\Config; +use \OCA\News\Utility\OPMLExporter; +use \OCA\News\Utility\Updater; +use \OCA\News\Utility\SimplePieAPIFactory; +use \OCA\News\Utility\TimeFactory; +use \OCA\News\Utility\FaviconFetcher; + +use \OCA\News\Fetcher\Fetcher; +use \OCA\News\Fetcher\FeedFetcher; + +use \OCA\News\ArticleEnhancer\Enhancer; +use \OCA\News\ArticleEnhancer\XPathArticleEnhancer; +use \OCA\News\ArticleEnhancer\RegexArticleEnhancer; + +use \OCA\News\Middleware\CORSMiddleware; + + +require_once __DIR__ . '/../3rdparty/htmlpurifier/library/HTMLPurifier.auto.php'; + +// to prevent clashes with installed app framework versions +if(!class_exists('\SimplePie')) { + require_once __DIR__ . '/../3rdparty/simplepie/autoloader.php'; +} + + +class News extends App { + + public function __construct(array $urlParams=array()){ + parent::__construct('news', $urlParams); + + $container = $this->getContainer(); + + + /** + * Controllers + */ + $container->registerService('PageController', function($c) { + return new PageController( + $c['API'], + $c['Request'] + ); + }); + + $container->registerService('FolderController', function($c) { + return new FolderController( + $c['API'], + $c['Request'], + $c['FolderBusinessLayer'], + $c['FeedBusinessLayer'], + $c['ItemBusinessLayer'] + ); + }); + + $container->registerService('FeedController', function($c) { + return new FeedController( + $c['API'], + $c['Request'], + $c['FolderBusinessLayer'], + $c['FeedBusinessLayer'], + $c['ItemBusinessLayer'] + ); + }); + + $container->registerService('ItemController', function($c) { + return new ItemController( + $c['API'], + $c['Request'], + $c['FeedBusinessLayer'], + $c['ItemBusinessLayer'] + ); + }); + + $container->registerService('ExportController', function($c) { + return new ExportController( + $c['API'], + $c['Request'], + $c['FeedBusinessLayer'], + $c['FolderBusinessLayer'], + $c['ItemBusinessLayer'], + $c['OPMLExporter']); + }); + + $container->registerService('ApiController', function($c) { + return new ApiController( + $c['API'], + $c['Request'], + $c['Updater'] + ); + }); + + $container->registerService('FolderApiController', function($c) { + return new FolderApiController( + $c['API'], + $c['Request'], + $c['FolderBusinessLayer'], + $c['ItemBusinessLayer'] + ); + }); + + $container->registerService('FeedApiController', function($c) { + return new FeedApiController( + $c['API'], + $c['Request'], + $c['FolderBusinessLayer'], + $c['FeedBusinessLayer'], + $c['ItemBusinessLayer'] + ); + }); + + $container->registerService('ItemApiController', function($c) { + return new ItemApiController( + $c['API'], + $c['Request'], + $c['ItemBusinessLayer'] + ); + }); + + + /** + * Business Layer + */ + $container->registerService('FolderBusinessLayer', function($c) { + return new FolderBusinessLayer( + $c['FolderMapper'], + $c['API'], + $c['TimeFactory'], + $c['Config'] + ); + }); + + $container->registerService('FeedBusinessLayer', function($c) { + return new FeedBusinessLayer( + $c['FeedMapper'], + $c['Fetcher'], + $c['ItemMapper'], + $c['API'], + $c['TimeFactory'], + $c['Config'] + $c['Enhancer'], + $c['HTMLPurifier'] + ); + }); + + $container->registerService('ItemBusinessLayer', function($c) { + return new ItemBusinessLayer( + $c['ItemMapper'], + $c['StatusFlag'], + $c['TimeFactory'], + $c['Config'] + ); + }); + + + /** + * Mappers + */ + $container->registerService('MapperFactory', function($c) { + return new MapperFactory( + $c['API'] + ); + }); + + $container->registerService('FolderMapper', function($c) { + return new FolderMapper( + $c['API'] + ); + }); + + $container->registerService('FeedMapper', function($c) { + return new FeedMapper( + $c['API'] + ); + }); + + $container->registerService('ItemMapper', function($c) { + return $c['MapperFactory']->getItemMapper( + $c['API'] + ); + }); + + + /** + * Utility + */ + $container->registerService('API', function($c){ + return new API( + $c['news'] + ); + }); + + $container->registerService('ConfigView', function($c) { + $view = new View('/news/config'); + if (!$view->file_exists('')) { + $view->mkdir(''); + } + + return $view; + }); + + $container->registerService('Config', function($c) { + $config = new Config($c['ConfigView'], $c['API']); + $config->read('config.ini', true); + return $config; + }); + + $container->registerService('simplePieCacheDirectory', function($c) { + $directory = $c['API']->getSystemValue('datadirectory') . + '/news/cache/simplepie'; + + if(!is_dir($directory)) { + mkdir($directory, 0770, true); + } + return $directory; + }); + + $container->registerService('HTMLPurifier', function($c) { + $directory = $c['API']->getSystemValue('datadirectory') . + '/news/cache/purifier'; + + if(!is_dir($directory)) { + mkdir($directory, 0770, true); + } + + $config = \HTMLPurifier_Config::createDefault(); + $config->set('HTML.ForbiddenAttributes', 'class'); + $config->set('Cache.SerializerPath', $directory); + $config->set('HTML.SafeIframe', true); + $config->set('URI.SafeIframeRegexp', + '%^(?:https?:)?//(' . + 'www.youtube(?:-nocookie)?.com/embed/|' . + 'player.vimeo.com/video/)%'); //allow YouTube and Vimeo + return new \HTMLPurifier($config); + }); + + $container->registerService('Enhancer', function($c) { + $enhancer = new Enhancer(); + + // register simple enhancers from config json file + $xpathEnhancerConfig = file_get_contents( + __DIR__ . '/../articleenhancer/xpathenhancers.json' + ); + + foreach(json_decode($xpathEnhancerConfig, true) as $feed => $config) { + $articleEnhancer = new XPathArticleEnhancer( + $c['SimplePieAPIFactory'], + $config, + $c['Config'] + ); + $enhancer->registerEnhancer($feed, $articleEnhancer); + } + + $regexEnhancerConfig = file_get_contents( + __DIR__ . '/../articleenhancer/regexenhancers.json' + ); + foreach(json_decode($regexEnhancerConfig, true) as $feed => $config) { + foreach ($config as $matchArticleUrl => $regex) { + $articleEnhancer = new RegexArticleEnhancer($matchArticleUrl, $regex); + $enhancer->registerEnhancer($feed, $articleEnhancer); + } + } + + return $enhancer; + }); + + /** + * Fetchers + */ + $container->registerService('Fetcher', function($c) { + $fetcher = new Fetcher(); + + // register fetchers in order + // the most generic fetcher should be the last one + $fetcher->registerFetcher($c['FeedFetcher']); + + return $fetcher; + }); + + $container->registerService('FeedFetcher', function($c) { + return new FeedFetcher( + $c['API'], + $c['SimplePieAPIFactory'], + $c['FaviconFetcher'], + $c['TimeFactory'], + $c['simplePieCacheDirectory'], + $c['Config'] + ); + }); + + $container->registerService('StatusFlag', function($c) { + return new StatusFlag(); + }); + + $container->registerService('OPMLExporter', function($c) { + return new OPMLExporter(); + }); + + $container->registerService('Updater', function($c) { + return new Updater( + $c['FolderBusinessLayer'], + $c['FeedBusinessLayer'], + $c['ItemBusinessLayer'] + ); + }); + + $container->registerService('SimplePieAPIFactory', function($c) { + return new SimplePieAPIFactory(); + }); + + $container->registerService('FaviconFetcher', function($c) { + return new FaviconFetcher( + $c['SimplePieAPIFactory'] + ); + }); + + /** + * Middleware + */ + $container->registerService('CORSMiddleware', function($c) { + return new CORSMiddleware( + $c['Request'] + ); + }); + + $container->registerMiddleWare($container['CORSMiddleware']); + + } +} + diff --git a/appinfo/routes.php b/appinfo/routes.php index 1eb0af953..d5d40c1a4 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -27,410 +27,95 @@ namespace OCA\News; use \OCP\AppFramework\App; -use \OCA\News\DependencyInjection\DIContainer; - -/** - * Webinterface - */ -$this->create('news_index', '/')->get()->action( - function($params){ - App::main('PageController', 'index', $params, new DIContainer()); - } -); - -/** - * Folders - */ -$this->create('news_folders', '/folders')->get()->action( - function($params){ - App::main('FolderController', 'folders', $params, new DIContainer()); - } -); - -$this->create('news_folders_open', '/folders/{folderId}/open')->post()->action( - function($params){ - App::main('FolderController', 'open', $params, new DIContainer()); - } -); - -$this->create('news_folders_collapse', '/folders/{folderId}/collapse')->post()->action( - function($params){ - App::main('FolderController', 'collapse', $params, new DIContainer()); - } -); - -$this->create('news_folders_create', '/folders')->post()->action( - function($params){ - App::main('FolderController', 'create', $params, new DIContainer()); - } -); - -$this->create('news_folders_delete', '/folders/{folderId}')->delete()->action( - function($params){ - App::main('FolderController', 'delete', $params, new DIContainer()); - } -); - -$this->create('news_folders_restore', '/folders/{folderId}/restore')->post()->action( - function($params){ - App::main('FolderController', 'restore', $params, new DIContainer()); - } -); - -$this->create('news_folders_rename', '/folders/{folderId}/rename')->post()->action( - function($params){ - App::main('FolderController', 'rename', $params, new DIContainer()); - } -); - -$this->create('news_folders_read', '/folders/{folderId}/read')->post()->action( - function($params){ - App::main('FolderController', 'read', $params, new DIContainer()); - } -); - -/** - * Feeds - */ -$this->create('news_feeds', '/feeds')->get()->action( - function($params){ - App::main('FeedController', 'feeds', $params, new DIContainer()); - } -); - -$this->create('news_feeds_active', '/feeds/active')->get()->action( - function($params){ - App::main('FeedController', 'active', $params, new DIContainer()); - } -); - -$this->create('news_feeds_create', '/feeds')->post()->action( - function($params){ - App::main('FeedController', 'create', $params, new DIContainer()); - } -); - -$this->create('news_feeds_delete', '/feeds/{feedId}')->delete()->action( - function($params){ - App::main('FeedController', 'delete', $params, new DIContainer()); - } -); - -$this->create('news_feeds_restore', '/feeds/{feedId}/restore')->post()->action( - function($params){ - App::main('FeedController', 'restore', $params, new DIContainer()); - } -); - -$this->create('news_feeds_update', '/feeds/{feedId}/update')->post()->action( - function($params){ - App::main('FeedController', 'update', $params, new DIContainer()); - } -); - -$this->create('news_feeds_move', '/feeds/{feedId}/move')->post()->action( - function($params){ - App::main('FeedController', 'move', $params, new DIContainer()); - } -); - -$this->create('news_feeds_rename', '/feeds/{feedId}/rename')->post()->action( - function($params){ - App::main('FeedController', 'rename', $params, new DIContainer()); - } -); - -$this->create('news_feeds_read', '/feeds/{feedId}/read')->post()->action( - function($params){ - App::main('FeedController', 'read', $params, new DIContainer()); - } -); - -$this->create('news_feeds_import_articles', '/feeds/import/articles') -->post()->action( - function($params){ - App::main('FeedController', 'importArticles', $params, - new DIContainer()); - } -); - -/** - * Items - */ -$this->create('news_items', '/items')->get()->action( - function($params){ - App::main('ItemController', 'items', $params, new DIContainer()); - } -); - -$this->create('news_items_new', '/items/new')->get()->action( - function($params){ - App::main('ItemController', 'newItems', $params, new DIContainer()); - } -); - -$this->create('news_items_read', '/items/{itemId}/read')->post()->action( - function($params){ - App::main('ItemController', 'read', $params, new DIContainer()); - } -); - -$this->create('news_items_unread', '/items/{itemId}/unread')->post()->action( - function($params){ - App::main('ItemController', 'unread', $params, new DIContainer()); - } -); - -$this->create('news_items_star', '/items/{feedId}/{guidHash}/star')->post()->action( - function($params){ - App::main('ItemController', 'star', $params, new DIContainer()); - } -); - -$this->create('news_items_unstar', '/items/{feedId}/{guidHash}/unstar')->post()->action( - function($params){ - App::main('ItemController', 'unstar', $params, new DIContainer()); - } -); - -$this->create('news_items_all_read', '/items/read')->post()->action( - function($params){ - App::main('ItemController', 'readAll', $params, new DIContainer()); - } -); - -/** - * Export - */ -$this->create('news_export_opml', '/export/opml')->get()->action( - function($params){ - App::main('ExportController', 'opml', $params, new DIContainer()); - } -); - -$this->create('news_export_articles', '/export/articles')->get()->action( - function($params){ - App::main('ExportController', 'articles', $params, new DIContainer()); - } -); - -/** - * User Settings - */ -$this->create('news_usersettings_iscompact', '/usersettings/compact')->get()->action( - function($params){ - App::main('UserSettingsController', 'isCompactView', $params, new DIContainer()); - } -); - -$this->create('news_usersettings_setcompact', '/usersettings/compact')->post()->action( - function($params){ - App::main('UserSettingsController', 'setCompactView', $params, new DIContainer()); - } -); - -$this->create('news_usersettings_read', '/usersettings/read')->get()->action( - function($params){ - App::main('UserSettingsController', 'read', $params, new DIContainer()); - } -); - -$this->create('news_usersettings_read_show', '/usersettings/read/show')->post()->action( - function($params){ - App::main('UserSettingsController', 'show', $params, new DIContainer()); - } -); - -$this->create('news_usersettings_read_hide', '/usersettings/read/hide')->post()->action( - function($params){ - App::main('UserSettingsController', 'hide', $params, new DIContainer()); - } -); - -$this->create('news_usersettings_language', '/usersettings/language')->get()->action( - function($params){ - App::main('UserSettingsController', 'getLanguage', $params, new DIContainer()); - } -); - - -/** - * Generic API - */ -$this->create('news_api_version', '/api/v1-2/version')->get()->action( - function($params) { - return App::main('NewsAPI', 'version', $params, new DIContainer()); - } -); - -$this->create('news_api_before_update', '/api/v1-2/cleanup/before-update')->get()->action( - function($params) { - return App::main('NewsAPI', 'beforeUpdate', $params, new DIContainer()); - } -); - -$this->create('news_api_after_update', '/api/v1-2/cleanup/after-update')->get()->action( - function($params) { - return App::main('NewsAPI', 'afterUpdate', $params, new DIContainer()); - } -); - -/** - * Folder API - */ -$this->create('news_api_folders_get_all', '/api/v1-2/folders')->get()->action( - function($params) { - return App::main('FolderAPI', 'getAll', $params, new DIContainer()); - } -); - -$this->create('news_api_folders_create', '/api/v1-2/folders')->post()->action( - function($params) { - return App::main('FolderAPI', 'create', $params, new DIContainer()); - } -); - -$this->create('news_api_folders_delete', '/api/v1-2/folders/{folderId}')->delete()->action( - function($params) { - return App::main('FolderAPI', 'delete', $params, new DIContainer()); - } -); - -$this->create('news_api_folders_update', '/api/v1-2/folders/{folderId}')->put()->action( - function($params) { - return App::main('FolderAPI', 'update', $params, new DIContainer()); - } -); - -$this->create('news_api_folders_read', '/api/v1-2/folders/{folderId}/read')->put()->action( - function($params) { - return App::main('FolderAPI', 'read', $params, new DIContainer()); - } -); - -/** - * Feed API - */ +use \OCA\News\App\News; + +$app = new News(); +$app->registerRoutes(array( + 'routes' => array( + ///////////////// Website + // page + array('name' => 'page#index', 'url' => '/', 'verb' => 'GET'), + array('name' => 'page#settings', 'url' => '/settings', 'verb' => 'GET'), + array('name' => 'page#update_settings', 'url' => '/settings', 'verb' => 'POST'), + + // folders + array('name' => 'folder#index', 'url' => '/folders', 'verb' => 'GET'), + array('name' => 'folder#create', 'url' => '/folders', 'verb' => 'POST'), + array('name' => 'folder#delete', 'url' => '/folders/{folderId}', 'verb' => 'DELETE'), + array('name' => 'folder#restore', 'url' => '/folders/{folderId}/restore', 'verb' => 'POST'), + array('name' => 'folder#rename', 'url' => '/folders/{folderId}/rename', 'verb' => 'POST'), + array('name' => 'folder#read', 'url' => '/folders/{folderId}/read', 'verb' => 'POST'), + array('name' => 'folder#open', 'url' => '/folders/{folderId}/open', 'verb' => 'POST'), + array('name' => 'folder#collapse', 'url' => '/folders/{folderId}/collapse', 'verb' => 'POST'), + + // feeds + array('name' => 'feed#index', 'url' => '/feeds', 'verb' => 'GET'), + array('name' => 'feed#create', 'url' => '/feeds', 'verb' => 'POST'), + array('name' => 'feed#delete', 'url' => '/feeds/{feedId}', 'verb' => 'DELETE'), + array('name' => 'feed#restore', 'url' => '/feeds/{feedId}/restore', 'verb' => 'POST'), + array('name' => 'feed#move', 'url' => '/feeds/{feedId}/move', 'verb' => 'POST'), + array('name' => 'feed#rename', 'url' => '/feeds/{feedId}/rename', 'verb' => 'POST'), + array('name' => 'feed#read', 'url' => '/feeds/{feedId}/read', 'verb' => 'POST'), + array('name' => 'feed#update', 'url' => '/feeds/{feedId}/update', 'verb' => 'POST'), + array('name' => 'feed#active', 'url' => '/feeds/active', 'verb' => 'GET'), + array('name' => 'feed#import', 'url' => '/feeds/import/articles', 'verb' => 'POST'), + + // items + array('name' => 'item#index', 'url' => '/items', 'verb' => 'GET'), + array('name' => 'item#new_items', 'url' => '/items/new', 'verb' => 'GET'), + array('name' => 'item#readAll', 'url' => '/items/read', 'verb' => 'POST'), + array('name' => 'item#read', 'url' => '/items/{itemId}/read', 'verb' => 'POST'), + array('name' => 'item#unread', 'url' => '/items/{itemId}/unread', 'verb' => 'POST'), + array('name' => 'item#star', 'url' => '/items/{feedId}/{guidHash}/star', 'verb' => 'POST'), + array('name' => 'item#unstar', 'url' => '/items/{feedId}/{guidHash}/unstar', 'verb' => 'POST'), + + // export + array('name' => 'export#opml', 'url' => '/export/opml', 'verb' => 'GET'), + array('name' => 'export#articles', 'url' => '/export/articles', 'verb' => 'GET'), + + ///////////////// API + // Generic + array('name' => 'api#version', 'url' => '/api/v1-2/version', 'verb' => 'GET'), + array('name' => 'api#update', 'url' => '/api/v1-2/update', 'verb' => 'GET'), + array('name' => 'api#before_update', 'url' => '/api/v1-2/cleanup/before-update', 'verb' => 'GET'), + array('name' => 'api#after_update', 'url' => '/api/v1-2/cleanup/after-update', 'verb' => 'GET'), + + // folders + array('name' => 'folder_api#index', 'url' => '/api/v1-2/folders', 'verb' => 'GET'), + array('name' => 'folder_api#create', 'url' => '/api/v1-2/folders', 'verb' => 'POST'), + array('name' => 'folder_api#put', 'url' => '/api/v1-2/folders/{folderId}', 'verb' => 'PUT'), + array('name' => 'folder_api#delete', 'url' => '/api/v1-2/folders/{folderId}', 'verb' => 'DELETE'), + array('name' => 'folder_api#read', 'url' => '/api/v1-2/folders/{folderId}/read', 'verb' => 'PUT'), // FIXME: POST would be more correct + + // feeds + array('name' => 'feed_api#index', 'url' => '/api/v1-2/feeds', 'verb' => 'GET'), + array('name' => 'feed_api#create', 'url' => '/api/v1-2/feeds', 'verb' => 'POST'), + array('name' => 'feed_api#put', 'url' => '/api/v1-2/feeds/{feedId}', 'verb' => 'PUT'), + array('name' => 'feed_api#delete', 'url' => '/api/v1-2/feeds/{feedId}', 'verb' => 'DELETE'), + array('name' => 'feed_api#from_all_users', 'url' => '/api/v1-2/feeds/all', 'verb' => 'GET'), + array('name' => 'feed_api#move', 'url' => '/api/v1-2/feeds/{feedId}/move', 'verb' => 'PUT'), // FIXME: POST would be more correct + array('name' => 'feed_api#rename', 'url' => '/api/v1-2/feeds/{feedId}/rename', 'verb' => 'PUT'), // FIXME: POST would be more correct + array('name' => 'feed_api#read', 'url' => '/api/v1-2/feeds/{feedId}/read', 'verb' => 'PUT'), // FIXME: POST would be more correct + + // items + array('name' => 'item_api#index', 'url' => '/api/v1-2/items', 'verb' => 'GET'), + array('name' => 'item_api#updated', 'url' => '/api/v1-2/items/updated', 'verb' => 'GET'), + array('name' => 'item_api#read', 'url' => '/api/v1-2/feeds/{itemId}/read', 'verb' => 'PUT'), // FIXME: POST would be more correct + array('name' => 'item_api#unread', 'url' => '/api/v1-2/feeds/{itemId}/unread', 'verb' => 'PUT'), // FIXME: POST would be more correct + array('name' => 'item_api#read_all', 'url' => '/api/v1-2/feeds/read', 'verb' => 'PUT'), // FIXME: POST would be more correct + array('name' => 'item_api#read_multiple', 'url' => '/api/v1-2/feeds/read/multiple', 'verb' => 'PUT'), // FIXME: POST would be more correct + array('name' => 'item_api#unread_multiple', 'url' => '/api/v1-2/feeds/unread/multiple', 'verb' => 'PUT'), // FIXME: POST would be more correct + array('name' => 'item_api#star', 'url' => '/api/v1-2/feeds/{feedId}/{guidHash}/star', 'verb' => 'PUT'), // FIXME: POST would be more correct + array('name' => 'item_api#unstar', 'url' => '/api/v1-2/feeds/{feedId}/{guidHash}/unstar', 'verb' => 'PUT'), // FIXME: POST would be more correct + array('name' => 'item_api#star_multiple', 'url' => '/api/v1-2/feeds/star/multiple', 'verb' => 'PUT'), // FIXME: POST would be more correct + array('name' => 'item_api#unstar_multiple', 'url' => '/api/v1-2/feeds/unstar/multiple', 'verb' => 'PUT'), // FIXME: POST would be more correct + ) +); + +/* TODO: FIX CORS $this->create('news_api_cors', '/api/v1-2/{path}')->method('options')->action( function($params) { return App::main('NewsAPI', 'cors', $params, new DIContainer()); } )->requirements(array('path' => '.+')); - - -$this->create('news_api_feeds_get_all', '/api/v1-2/feeds')->get()->action( - function($params) { - return App::main('FeedAPI', 'getAll', $params, new DIContainer()); - } -); - -$this->create('news_api_feeds_get_all_from_all_users', '/api/v1-2/feeds/all')->get()->action( - function($params) { - return App::main('FeedAPI', 'getAllFromAllUsers', $params, new DIContainer()); - } -); - -$this->create('news_api_feeds_create', '/api/v1-2/feeds')->post()->action( - function($params) { - return App::main('FeedAPI', 'create', $params, new DIContainer()); - } -); - -$this->create('news_api_feeds_update', '/api/v1-2/feeds/update')->get()->action( - function($params) { - return App::main('FeedAPI', 'update', $params, new DIContainer()); - } -); - -$this->create('news_api_feeds_delete', '/api/v1-2/feeds/{feedId}')->delete()->action( - function($params) { - return App::main('FeedAPI', 'delete', $params, new DIContainer()); - } -); - -$this->create('news_api_feeds_move', '/api/v1-2/feeds/{feedId}/move')->put()->action( - function($params) { - return App::main('FeedAPI', 'move', $params, new DIContainer()); - } -); - -$this->create('news_api_feeds_rename', '/api/v1-2/feeds/{feedId}/rename')->put()->action( - function($params) { - return App::main('FeedAPI', 'rename', $params, new DIContainer()); - } -); - -$this->create('news_api_feeds_read', '/api/v1-2/feeds/{feedId}/read')->put()->action( - function($params) { - return App::main('FeedAPI', 'read', $params, new DIContainer()); - } -); - -/** - * Item API - */ -$this->create('news_api_items_get_all', '/api/v1-2/items')->get()->action( - function($params) { - return App::main('ItemAPI', 'getAll', $params, new DIContainer()); - } -); - -$this->create('news_api_items_updated', '/api/v1-2/items/updated')->get()->action( - function($params) { - return App::main('ItemAPI', 'getUpdated', $params, new DIContainer()); - } -); - -$this->create('news_api_items_read', '/api/v1-2/items/{itemId}/read')->put()->action( - function($params) { - return App::main('ItemAPI', 'read', $params, new DIContainer()); - } -); - -$this->create('news_api_items_unread', '/api/v1-2/items/{itemId}/unread')->put()->action( - function($params) { - return App::main('ItemAPI', 'unread', $params, new DIContainer()); - } -); - -$this->create('news_api_items_star', '/api/v1-2/items/{feedId}/{guidHash}/star')->put()->action( - function($params) { - return App::main('ItemAPI', 'star', $params, new DIContainer()); - } -); - -$this->create('news_api_items_unstar', '/api/v1-2/items/{feedId}/{guidHash}/unstar')->put()->action( - function($params) { - return App::main('ItemAPI', 'unstar', $params, new DIContainer()); - } -); - -$this->create('news_api_items_read_all', '/api/v1-2/items/read')->put()->action( - function($params) { - return App::main('ItemAPI', 'readAll', $params, new DIContainer()); - } -); - -$this->create('news_api_items_read_multiple', '/api/v1-2/items/read/multiple')->put()->action( - function($params) { - return App::main('ItemAPI', 'readMultiple', $params, new DIContainer()); - } -); - -$this->create('news_api_items_unread_multiple', '/api/v1-2/items/unread/multiple')->put()->action( - function($params) { - return App::main('ItemAPI', 'unreadMultiple', $params, new DIContainer()); - } -); - -$this->create('news_api_items_star_multiple', '/api/v1-2/items/star/multiple')->put()->action( - function($params) { - return App::main('ItemAPI', 'starMultiple', $params, new DIContainer()); - } -); - -$this->create('news_api_items_unstar_multiple', '/api/v1-2/items/unstar/multiple')->put()->action( - function($params) { - return App::main('ItemAPI', 'unstarMultiple', $params, new DIContainer()); - } -); +*/ \ No newline at end of file diff --git a/articleenhancer/xpatharticleenhancer.php b/articleenhancer/xpatharticleenhancer.php index 586f65151..50dc402cc 100644 --- a/articleenhancer/xpatharticleenhancer.php +++ b/articleenhancer/xpatharticleenhancer.php @@ -25,8 +25,9 @@ namespace OCA\News\ArticleEnhancer; -use \OCA\News\Utility\SimplePieAPIFactory; use \OCA\News\Db\Item; +use \OCA\News\Utility\SimplePieAPIFactory; +use \OCA\News\Utility\Config; class XPathArticleEnhancer implements ArticleEnhancer { @@ -45,10 +46,10 @@ class XPathArticleEnhancer implements ArticleEnhancer { * @param int $maximumTimeout maximum timeout in seconds, defaults to 10 sec */ public function __construct(SimplePieAPIFactory $fileFactory, - array $regexXPathPair, $maximumTimeout=10){ + array $regexXPathPair, Config $config){ $this->regexXPathPair = $regexXPathPair; $this->fileFactory = $fileFactory; - $this->maximumTimeout = $maximumTimeout; + $this->maximumTimeout = $config->getFeedFetcherTimeout(); } diff --git a/businesslayer/feedbusinesslayer.php b/businesslayer/feedbusinesslayer.php index 76763aae7..1322bc73f 100644 --- a/businesslayer/feedbusinesslayer.php +++ b/businesslayer/feedbusinesslayer.php @@ -34,7 +34,8 @@ use \OCA\News\Db\ItemMapper; use \OCA\News\Fetcher\Fetcher; use \OCA\News\Fetcher\FetcherException; use \OCA\News\ArticleEnhancer\Enhancer; -use \OCA\News\Utility\TimeFactory; +use \OCA\News\Utility\Config; + class FeedBusinessLayer extends BusinessLayer { @@ -48,8 +49,8 @@ class FeedBusinessLayer extends BusinessLayer { public function __construct(FeedMapper $feedMapper, Fetcher $feedFetcher, ItemMapper $itemMapper, API $api, - TimeFactory $timeFactory, - $autoPurgeMinimumInterval, + $timeFactory, + Config $config, Enhancer $enhancer, $purifier){ parent::__construct($feedMapper); @@ -57,7 +58,7 @@ class FeedBusinessLayer extends BusinessLayer { $this->itemMapper = $itemMapper; $this->api = $api; $this->timeFactory = $timeFactory; - $this->autoPurgeMinimumInterval = $autoPurgeMinimumInterval; + $this->autoPurgeMinimumInterval = $config->getAutoPurgeMinimumInterval(); $this->enhancer = $enhancer; $this->purifier = $purifier; } diff --git a/businesslayer/folderbusinesslayer.php b/businesslayer/folderbusinesslayer.php index c8611917a..80634abc8 100644 --- a/businesslayer/folderbusinesslayer.php +++ b/businesslayer/folderbusinesslayer.php @@ -28,7 +28,7 @@ namespace OCA\News\BusinessLayer; use \OCA\News\Core\API; use \OCA\News\Db\Folder; use \OCA\News\Db\FolderMapper; -use \OCA\News\Utility\TimeFactory; +use \OCA\News\Utility\Config; class FolderBusinessLayer extends BusinessLayer { @@ -39,12 +39,12 @@ class FolderBusinessLayer extends BusinessLayer { public function __construct(FolderMapper $folderMapper, API $api, - TimeFactory $timeFactory, - $autoPurgeMinimumInterval){ + $timeFactory, + Config $config){ parent::__construct($folderMapper); $this->api = $api; $this->timeFactory = $timeFactory; - $this->autoPurgeMinimumInterval = $autoPurgeMinimumInterval; + $this->autoPurgeMinimumInterval = $config->getAutoPurgeMinimumInterval(); } /** diff --git a/businesslayer/itembusinesslayer.php b/businesslayer/itembusinesslayer.php index 545ed565b..7558667cf 100644 --- a/businesslayer/itembusinesslayer.php +++ b/businesslayer/itembusinesslayer.php @@ -30,7 +30,7 @@ use \OCA\News\Db\ItemMapper; use \OCA\News\Db\StatusFlag; use \OCA\News\Db\FeedType; use \OCA\News\Db\DoesNotExistException; -use \OCA\News\Utility\TimeFactory; +use \OCA\News\Utility\Config; class ItemBusinessLayer extends BusinessLayer { @@ -40,10 +40,10 @@ class ItemBusinessLayer extends BusinessLayer { private $timeFactory; public function __construct(ItemMapper $itemMapper, StatusFlag $statusFlag, - TimeFactory $timeFactory, $autoPurgeCount=0){ + $timeFactory, Config $config){ parent::__construct($itemMapper); $this->statusFlag = $statusFlag; - $this->autoPurgeCount = $autoPurgeCount; + $this->autoPurgeCount = $config->getAutoPurgeCount(); $this->timeFactory = $timeFactory; } diff --git a/controller/apicontroller.php b/controller/apicontroller.php new file mode 100644 index 000000000..9e0ff2401 --- /dev/null +++ b/controller/apicontroller.php @@ -0,0 +1,106 @@ +. +* +*/ + +namespace OCA\News\Controller; + +use \OCP\IRequest; +use \OCP\AppFramework\Controller; +use \OCP\AppFramework\Http; +use \OCP\AppFramework\Http\JSONResponse; +use \OCP\AppFramework\Http\Response; + +use \OCA\News\Utility\Updater; +use \OCA\News\Core\API; + +class ApiController extends Controller { + + private $updater; + private $api; + + public function __construct(API $api, IRequest $request, Updater $updater){ + parent::__construct($api->getAppName(), $request); + $this->updater = $updater; + $this->api = $api; + } + + + /** + * @NoAdminRequired + * @NoCSRFRequired + * @API + */ + public function version() { + $version = $this->api->getAppValue('installed_version'); + $response = new JSONResponse(array('version' => $version)); + return $response; + } + + + /** + * @NoCSRFRequired + * @API + */ + public function beforeUpdate() { + $this->updater->beforeUpdate(); + return new JSONResponse(); + } + + + /** + * @NoCSRFRequired + * @API + */ + public function afterUpdate() { + $this->updater->afterUpdate(); + return new JSONResponse(); + } + + + /** + * @NoAdminRequired + * @NoCSRFRequired + * @PublicPage + */ + public function cors() { + // needed for webapps access due to cross origin request policy + if(isset($this->request->server['HTTP_ORIGIN'])) { + $origin = $this->request->server['HTTP_ORIGIN']; + } else { + $origin = '*'; + } + + $response = new Response(); + $response->addHeader('Access-Control-Allow-Origin', $origin); + $response->addHeader('Access-Control-Allow-Methods', + 'PUT, POST, GET, DELETE'); + $response->addHeader('Access-Control-Allow-Credentials', 'true'); + $response->addHeader('Access-Control-Max-Age', '1728000'); + $response->addHeader('Access-Control-Allow-Headers', + 'Authorization, Content-Type'); + return $response; + } + + +} diff --git a/controller/feedapicontroller.php b/controller/feedapicontroller.php new file mode 100644 index 000000000..6537e51df --- /dev/null +++ b/controller/feedapicontroller.php @@ -0,0 +1,236 @@ +. +* +*/ + +namespace OCA\News\Controller; + +use \OCP\IRequest; +use \OCP\AppFramework\Controller; +use \OCP\AppFramework\Http; +use \OCP\AppFramework\Http\JSONResponse; + +use \OCA\News\Core\API; +use \OCA\News\BusinessLayer\FeedBusinessLayer; +use \OCA\News\BusinessLayer\FolderBusinessLayer; +use \OCA\News\BusinessLayer\ItemBusinessLayer; +use \OCA\News\BusinessLayer\BusinessLayerException; +use \OCA\News\BusinessLayer\BusinessLayerConflictException; + + +class FeedApiController extends Controller { + + private $itemBusinessLayer; + private $feedBusinessLayer; + private $folderBusinessLayer; + private $api; + + public function __construct(API $api, + IRequest $request, + FolderBusinessLayer $folderBusinessLayer, + FeedBusinessLayer $feedBusinessLayer, + ItemBusinessLayer $itemBusinessLayer){ + parent::__construct($api->getAppName(), $request); + $this->folderBusinessLayer = $folderBusinessLayer; + $this->feedBusinessLayer = $feedBusinessLayer; + $this->itemBusinessLayer = $itemBusinessLayer; + $this->api = $api; + } + + + /** + * @NoAdminRequired + * @NoCSRFRequired + * @API + */ + public function index() { + $userId = $this->api->getUserId(); + + $result = array( + 'feeds' => array(), + 'starredCount' => $this->itemBusinessLayer->starredCount($userId) + ); + + foreach ($this->feedBusinessLayer->findAll($userId) as $feed) { + array_push($result['feeds'], $feed->toAPI()); + } + + // check case when there are no items + try { + $result['newestItemId'] = + $this->itemBusinessLayer->getNewestItemId($userId); + } catch(BusinessLayerException $ex) {} + + return new JSONResponse($result); + } + + + /** + * @NoAdminRequired + * @NoCSRFRequired + * @API + */ + public function create() { + $userId = $this->api->getUserId(); + $feedUrl = $this->params('url'); + $folderId = (int) $this->params('folderId', 0); + + try { + $this->feedBusinessLayer->purgeDeleted($userId, false); + + $feed = $this->feedBusinessLayer->create($feedUrl, $folderId, $userId); + $result = array( + 'feeds' => array($feed->toAPI()) + ); + + try { + $result['newestItemId'] = + $this->itemBusinessLayer->getNewestItemId($userId); + } catch(BusinessLayerException $ex) {} + + return new JSONResponse($result); + + } catch(BusinessLayerConflictException $ex) { + return new JSONResponse(array('message' => $ex->getMessage()), + Http::STATUS_CONFLICT); + } catch(BusinessLayerException $ex) { + return new JSONResponse(array('message' => $ex->getMessage()), + Http::STATUS_NOT_FOUND); + } + } + + + /** + * @NoAdminRequired + * @NoCSRFRequired + * @API + */ + public function delete() { + $userId = $this->api->getUserId(); + $feedId = (int) $this->params('feedId'); + + try { + $this->feedBusinessLayer->delete($feedId, $userId); + return new JSONResponse(); + } catch(BusinessLayerException $ex) { + return new JSONResponse(array('message' => $ex->getMessage()), + Http::STATUS_NOT_FOUND); + } + } + + + /** + * @NoAdminRequired + * @NoCSRFRequired + * @API + */ + public function read() { + $userId = $this->api->getUserId(); + $feedId = (int) $this->params('feedId'); + $newestItemId = (int) $this->params('newestItemId'); + + $this->itemBusinessLayer->readFeed($feedId, $newestItemId, $userId); + return new JSONResponse(); + } + + + /** + * @NoAdminRequired + * @NoCSRFRequired + * @API + */ + public function move() { + $userId = $this->api->getUserId(); + $feedId = (int) $this->params('feedId'); + $folderId = (int) $this->params('folderId'); + + try { + $this->feedBusinessLayer->move($feedId, $folderId, $userId); + return new JSONResponse(); + } catch(BusinessLayerException $ex) { + return new JSONResponse(array('message' => $ex->getMessage()), + Http::STATUS_NOT_FOUND); + } + } + + + /** + * @NoAdminRequired + * @NoCSRFRequired + * @API + */ + public function rename() { + $userId = $this->api->getUserId(); + $feedId = (int) $this->params('feedId'); + $feedTitle = $this->params('feedTitle'); + + try { + $this->feedBusinessLayer->rename($feedId, $feedTitle, $userId); + return new JSONResponse(); + } catch(BusinessLayerException $ex) { + return new JSONResponse(array('message' => $ex->getMessage()), + Http::STATUS_NOT_FOUND); + } + } + + + /** + * @NoCSRFRequired + * @API + */ + public function fromAllUsers() { + $feeds = $this->feedBusinessLayer->findAllFromAllUsers(); + $result = array('feeds' => array()); + + foreach ($feeds as $feed) { + array_push($result['feeds'], array( + 'id' => $feed->getId(), + 'userId' => $feed->getUserId() + )); + } + + return new JSONResponse($result); + } + + + /** + * @NoCSRFRequired + * @API + */ + public function update() { + $userId = $this->params('userId'); + $feedId = (int) $this->params('feedId'); + + try { + $this->feedBusinessLayer->update($feedId, $userId); + // ignore update failure (feed could not be reachable etc, we dont care) + } catch(\Exception $ex) { + $this->api->log('Could not update feed ' . $ex->getMessage(), + 'debug'); + } + return new JSONResponse(); + + } + +