diff options
author | Bernhard Posselt <dev@bernhard-posselt.com> | 2014-05-29 22:58:30 +0200 |
---|---|---|
committer | Bernhard Posselt <dev@bernhard-posselt.com> | 2014-05-29 22:58:30 +0200 |
commit | cba949fb0771c832326fc7886cced2bdc37e7536 (patch) | |
tree | 9e1a335a83a6006f645c801b762db7525e4c6c59 | |
parent | b91ef01fdbf14c6a5d58e5c471dbb1fc9d17cdfb (diff) |
order by pubdate
-rw-r--r-- | controller/entityapiserializer.php | 11 | ||||
-rw-r--r-- | controller/feedapicontroller.php | 15 | ||||
-rw-r--r-- | controller/folderapicontroller.php | 11 | ||||
-rw-r--r-- | controller/foldercontroller.php | 38 | ||||
-rw-r--r-- | controller/itemapicontroller.php | 29 | ||||
-rw-r--r-- | controller/itemcontroller.php | 3 | ||||
-rw-r--r-- | db/itemmapper.php | 35 | ||||
-rw-r--r-- | js/build/app.js | 63 | ||||
-rw-r--r-- | js/controller/ContentController.js | 36 | ||||
-rw-r--r-- | js/service/FeedResource.js | 4 | ||||
-rw-r--r-- | js/service/ItemResource.js | 44 | ||||
-rw-r--r-- | js/tests/unit/controller/ContentControllerSpec.js | 122 | ||||
-rw-r--r-- | js/tests/unit/service/ItemResourceSpec.js | 73 | ||||
-rw-r--r-- | service/itemservice.php | 18 | ||||
-rw-r--r-- | tests/unit/controller/FeedApiControllerTest.php | 8 | ||||
-rw-r--r-- | tests/unit/controller/FolderApiControllerTest.php | 10 | ||||
-rw-r--r-- | tests/unit/controller/ItemApiControllerTest.php | 18 | ||||
-rw-r--r-- | tests/unit/controller/ItemControllerTest.php | 8 | ||||
-rw-r--r-- | tests/unit/db/ItemMapperTest.php | 91 | ||||
-rw-r--r-- | tests/unit/service/ItemServiceTest.php | 27 |
20 files changed, 347 insertions, 317 deletions
diff --git a/controller/entityapiserializer.php b/controller/entityapiserializer.php index c09e27dbd..eb60bc7c5 100644 --- a/controller/entityapiserializer.php +++ b/controller/entityapiserializer.php @@ -11,13 +11,12 @@ namespace OCA\News\Controller; -use \OCP\AppFramework\Http\IResponseSerializer; use \OCP\AppFramework\Http\Response; use \OCA\News\Db\IAPI; -class EntityApiSerializer implements IResponseSerializer { +class EntityApiSerializer { public function __construct($level) { @@ -35,10 +34,6 @@ class EntityApiSerializer implements IResponseSerializer { */ public function serialize($data) { - if($data === null || $data instanceof Response) { - return $data; - } - if($data instanceof IAPI) { return [$this->level => [$data->toAPI()]]; } @@ -58,14 +53,14 @@ class EntityApiSerializer implements IResponseSerializer { foreach($entities as $entity) { if($entity instanceof IAPI) { - $converted[] = $entity->toAPI(); + $converted[] = $entity->toAPI(); // break if it contains anything else than entities } else { return $entities; } } - + return $converted; } diff --git a/controller/feedapicontroller.php b/controller/feedapicontroller.php index c6b5b6866..4ba3b9be5 100644 --- a/controller/feedapicontroller.php +++ b/controller/feedapicontroller.php @@ -33,6 +33,7 @@ class FeedApiController extends ApiController { private $userId; private $logger; private $loggerParams; + private $serializer; public function __construct($appName, IRequest $request, @@ -47,7 +48,7 @@ class FeedApiController extends ApiController { $this->userId = $userId; $this->logger = $logger; $this->loggerParams = $loggerParams; - $this->registerSerializer(new EntityApiSerializer('feeds')); + $this->serializer = new EntityApiSerializer('feeds'); } @@ -64,14 +65,14 @@ class FeedApiController extends ApiController { 'feeds' => $this->feedService->findAll($this->userId) ]; - + try { $result['newestItemId'] = $this->itemService->getNewestItemId($this->userId); - + // in case there are no items, ignore } catch(ServiceNotFoundException $ex) {} - return $result; + return $this->serializer->serialize($result); } @@ -96,7 +97,7 @@ class FeedApiController extends ApiController { // in case there are no items, ignore } catch(ServiceNotFoundException $ex) {} - return $result; + return $this->serializer->serialize($result); } catch(ServiceConflictException $ex) { return $this->error($ex, Http::STATUS_CONFLICT); @@ -110,7 +111,7 @@ class FeedApiController extends ApiController { * @NoAdminRequired * @NoCSRFRequired * @CORS - * + * * @param int $feedId */ public function delete($feedId) { @@ -179,7 +180,7 @@ class FeedApiController extends ApiController { foreach ($feeds as $feed) { $result['feeds'][] = [ - 'id' => $feed->getId(), + 'id' => $feed->getId(), 'userId' => $feed->getUserId() ]; } diff --git a/controller/folderapicontroller.php b/controller/folderapicontroller.php index c5ed2b05a..666f4cfa2 100644 --- a/controller/folderapicontroller.php +++ b/controller/folderapicontroller.php @@ -31,6 +31,7 @@ class FolderApiController extends ApiController { private $folderService; private $itemService; private $userId; + private $serializer; public function __construct($appName, IRequest $request, @@ -41,7 +42,7 @@ class FolderApiController extends ApiController { $this->folderService = $folderService; $this->itemService = $itemService; $this->userId = $userId; - $this->registerSerializer(new EntityApiSerializer('folders')); + $this->serializer = new EntityApiSerializer('folders'); } @@ -51,7 +52,9 @@ class FolderApiController extends ApiController { * @CORS */ public function index() { - return $this->folderService->findAll($this->userId); + return $this->serializer->serialize( + $this->folderService->findAll($this->userId) + ); } @@ -65,7 +68,9 @@ class FolderApiController extends ApiController { public function create($name) { try { $this->folderService->purgeDeleted($this->userId, false); - return $this->folderService->create($name, $this->userId); + return $this->serializer->serialize( + $this->folderService->create($name, $this->userId) + ); } catch(ServiceValidationException $ex) { return $this->error($ex, Http::STATUS_UNPROCESSABLE_ENTITY); } catch(ServiceConflictException $ex) { diff --git a/controller/foldercontroller.php b/controller/foldercontroller.php index 4a19ab513..1137a2528 100644 --- a/controller/foldercontroller.php +++ b/controller/foldercontroller.php @@ -34,12 +34,12 @@ class FolderController extends Controller { private $itemService; private $userId; - public function __construct($appName, - IRequest $request, + public function __construct($appName, + IRequest $request, FolderService $folderService, FeedService $feedService, ItemService $itemService, - $userId){ + $userId) { parent::__construct($appName, $request); $this->folderService = $folderService; $this->feedService = $feedService; @@ -51,23 +51,23 @@ class FolderController extends Controller { /** * @NoAdminRequired */ - public function index(){ + public function index() { $folders = $this->folderService->findAll($this->userId); return ['folders' => $folders]; } - private function setOpened($isOpened, $folderId){ + private function setOpened($isOpened, $folderId) { $this->folderService->open($folderId, $isOpened, $this->userId); } /** * @NoAdminRequired - * + * * @param int $folderId */ - public function open($folderId){ + public function open($folderId) { try { $this->setOpened(true, $folderId); } catch(ServiceNotFoundException $ex) { @@ -81,7 +81,7 @@ class FolderController extends Controller { * * @param int $folderId */ - public function collapse($folderId){ + public function collapse($folderId) { try { $this->setOpened(false, $folderId); } catch(ServiceNotFoundException $ex) { @@ -95,9 +95,9 @@ class FolderController extends Controller { * * @param string $folderName */ - public function create($folderName){ + public function create($folderName) { try { - // we need to purge deleted folders if a folder is created to + // we need to purge deleted folders if a folder is created to // prevent already exists exceptions $this->folderService->purgeDeleted($this->userId, false); $folder = $this->folderService->create($folderName, $this->userId); @@ -109,16 +109,16 @@ class FolderController extends Controller { } catch(ServiceValidationException $ex) { return $this->error($ex, Http::STATUS_UNPROCESSABLE_ENTITY); } - + } /** * @NoAdminRequired - * + * * @param int $folderId */ - public function delete($folderId){ + public function delete($folderId) { try { $this->folderService->markDeleted($folderId, $this->userId); } catch (ServiceNotFoundException $ex){ @@ -133,9 +133,9 @@ class FolderController extends Controller { * @param string $folderName * @param int $folderId */ - public function rename($folderName, $folderId){ + public function rename($folderName, $folderId) { try { - $folder = $this->folderService->rename($folderId, $folderName, + $folder = $this->folderService->rename($folderId, $folderName, $this->userId); return ['folders' => [$folder]]; @@ -143,7 +143,7 @@ class FolderController extends Controller { } catch(ServiceConflictException $ex) { return $this->error($ex, Http::STATUS_CONFLICT); } catch(ServiceValidationException $ex) { - return $this->error($ex, Http::STATUS_UNPROCESSABLE_ENTITY); + return $this->error($ex, Http::STATUS_UNPROCESSABLE_ENTITY); } catch (ServiceNotFoundException $ex){ return $this->error($ex, Http::STATUS_NOT_FOUND); } @@ -155,7 +155,7 @@ class FolderController extends Controller { * @param int $folderId * @param int $highestItemId */ - public function read($folderId, $highestItemId){ + public function read($folderId, $highestItemId) { $this->itemService->readFolder($folderId, $highestItemId, $this->userId); return ['feeds' => $this->feedService->findAll($this->userId)]; @@ -164,10 +164,10 @@ class FolderController extends Controller { /** * @NoAdminRequired - * + * * @param int $folderId */ - public function restore($folderId){ + public function restore($folderId) { try { $this->folderService->unmarkDeleted($folderId, $this->userId); } catch (ServiceNotFoundException $ex){ diff --git a/controller/itemapicontroller.php b/controller/itemapicontroller.php index da4596d1e..40366a936 100644 --- a/controller/itemapicontroller.php +++ b/controller/itemapicontroller.php @@ -26,6 +26,7 @@ class ItemApiController extends ApiController { private $itemService; private $userId; + private $serializer; public function __construct($appName, IRequest $request, @@ -34,7 +35,7 @@ class ItemApiController extends ApiController { parent::__construct($appName, $request); $this->itemService = $itemService; $this->userId = $userId; - $this->registerSerializer(new EntityApiSerializer('items')); + $this->serializer = new EntityApiSerializer('items'); } @@ -42,16 +43,22 @@ class ItemApiController extends ApiController { * @NoAdminRequired * @NoCSRFRequired * @CORS - * + * * @param int $type * @param int $id * @param bool $getRead * @param int $batchSize * @param int $offset + * @param int $oldestFirst */ - public function index($type, $id, $getRead, $batchSize=20, $offset=0) { - return $this->itemService->findAll($id, $type, $batchSize, $offset, - $getRead, $this->userId); + public function index($type, $id, $getRead, $batchSize=20, $offset=0, + $oldestFirst=false) { + return $this->serializer->serialize( + $this->itemService->findAll( + $id, $type, $batchSize, $offset, $getRead, $oldestFirst, + $this->userId + ) + ); } @@ -59,14 +66,16 @@ class ItemApiController extends ApiController { * @NoAdminRequired * @NoCSRFRequired * @CORS - * + * * @param int $type * @param int $id * @param int $lastModified */ public function updated($type, $id, $lastModified=0) { - return $this->itemService->findAllNew($id, $type, $lastModified, - true, $this->userId); + return $this->serializer->serialize( + $this->itemService->findAllNew($id, $type, $lastModified, + true, $this->userId) + ); } @@ -188,7 +197,7 @@ class ItemApiController extends ApiController { private function setMultipleStarred($isStarred, $items) { foreach($items as $item) { try { - $this->itemService->star($item['feedId'], $item['guidHash'], + $this->itemService->star($item['feedId'], $item['guidHash'], $isStarred, $this->userId); } catch(ServiceNotFoundException $ex) { continue; @@ -213,7 +222,7 @@ class ItemApiController extends ApiController { * @NoAdminRequired * @NoCSRFRequired * @CORS - * + * * @param int[] item ids */ public function unstarMultiple($items) { diff --git a/controller/itemcontroller.php b/controller/itemcontroller.php index 486d0b922..4f3f22c62 100644 --- a/controller/itemcontroller.php +++ b/controller/itemcontroller.php @@ -80,7 +80,8 @@ class ItemController extends Controller { } $params['items'] = $this->itemService->findAll( - $id, $type, $limit, $offset, $showAll, $this->userId, $oldestFirst + $id, $type, $limit, $offset, $showAll, $oldestFirst, + $this->userId ); // this gets thrown if there are no items diff --git a/db/itemmapper.php b/db/itemmapper.php index d3c8164ae..477848a32 100644 --- a/db/itemmapper.php +++ b/db/itemmapper.php @@ -41,7 +41,7 @@ class ItemMapper extends Mapper implements IMapper { 'ON `folders`.`id` = `feeds`.`folder_id` ' . 'WHERE `feeds`.`folder_id` = 0 ' . 'OR `folders`.`deleted_at` = 0 ' . - 'ORDER BY `items`.`id` ' . $ordering; + 'ORDER BY `items`.`pub_date`, `items`.`id` ' . $ordering; } private function makeSelectQueryStatus($prependTo, $status, $oldestFirst=false) { @@ -174,39 +174,28 @@ class ItemMapper extends Mapper implements IMapper { } } - public function findAllFeed($id, $limit, $offset, $status, $userId, $oldestFirst=false){ + public function findAllFeed($id, $limit, $offset, $status, $oldestFirst, + $userId){ $params = [$userId, $id]; $sql = 'AND `items`.`feed_id` = ? '; - if($offset !== 0){ - $sql .= 'AND `items`.`id` ' . $this->getOperator($oldestFirst) . ' ? '; - $params[] = $offset; - } $sql = $this->makeSelectQueryStatus($sql, $status, $oldestFirst); - return $this->findEntities($sql, $params, $limit); + return $this->findEntities($sql, $params, $limit, $offset); } - public function findAllFolder($id, $limit, $offset, $status, $userId, $oldestFirst=false){ + public function findAllFolder($id, $limit, $offset, $status, $oldestFirst, + $userId){ $params = [$userId, $id]; $sql = 'AND `feeds`.`folder_id` = ? '; - if($offset !== 0){ - $sql .= 'AND `items`.`id` ' . $this->getOperator($oldestFirst) . ' ? '; - $params[] = $offset; - } $sql = $this->makeSelectQueryStatus($sql, $status, $oldestFirst); - return $this->findEntities($sql, $params, $limit); + return $this->findEntities($sql, $params, $limit, $offset); } - public function findAll($limit, $offset, $status, $userId, $oldestFirst=false){ + public function findAll($limit, $offset, $status, $oldestFirst, $userId){ $params = [$userId]; - $sql = ''; - if($offset !== 0){ - $sql .= 'AND `items`.`id` ' . $this->getOperator($oldestFirst) . ' ? '; - $params[] = $offset; - } - $sql = $this->makeSelectQueryStatus($sql, $status, $oldestFirst); - return $this->findEntities($sql, $params, $limit); + $sql = $this->makeSelectQueryStatus('', $status, $oldestFirst); + return $this->findEntities($sql, $params, $limit, $offset); } @@ -235,7 +224,7 @@ class ItemMapper extends Mapper implements IMapper { public function deleteReadOlderThanThreshold($threshold){ $status = StatusFlag::STARRED | StatusFlag::UNREAD; $sql = 'SELECT COUNT(*) - `feeds`.`articles_per_update` AS `size`, ' . - '`items`.`feed_id` AS `feed_id` ' . + '`items`.`feed_id` AS `feed_id` ' . 'FROM `*PREFIX*news_items` `items` ' . 'JOIN `*PREFIX*news_feeds` `feeds` ' . 'ON `feeds`.`id` = `items`.`feed_id` ' . @@ -282,7 +271,7 @@ class ItemMapper extends Mapper implements IMapper { * @param string $userId the name of the user */ public function deleteUser($userId) { - $sql = 'DELETE FROM `*PREFIX*news_items` ' . + $sql = 'DELETE FROM `*PREFIX*news_items` ' . 'WHERE `feed_id` IN (' . 'SELECT `feeds`.`id` FROM `*PREFIX*news_feeds` `feeds` ' . 'WHERE `feeds`.`user_id` = ?' . diff --git a/js/build/app.js b/js/build/app.js index e0472f32c..3e0e5624e 100644 --- a/js/build/app.js +++ b/js/build/app.js @@ -189,19 +189,23 @@ var $__build_47_app__ = function () { return ItemResource.getAll(); }; this.toggleStar = function (itemId) { - console.log(itemId); + ItemResource.toggleStar(itemId); }; this.markRead = function (itemId) { - console.log(itemId); + ItemResource.markItemRead(itemId); + var item = ItemResource.get(itemId); + FeedResource.markItemOfFeedRead(item.feedId); }; this.getFeed = function (feedId) { - console.log(feedId); + return FeedResource.getById(feedId); }; - this.keepUnread = function (itemId) { - console.log(itemId); - }; - this.isContentView = function () { - console.log('tbd'); + this.toggleKeepUnread = function (itemId) { + var item = ItemResource.get(itemId); + if (!item.unread) { + FeedResource.markItemOfFeedUnread(item.feedId); + ItemResource.markItemRead(itemId, false); + } + item.keepUnread = !item.keepUnread; }; this.orderBy = function () { if (SettingsResource.get('oldestFirst')) { @@ -210,9 +214,18 @@ var $__build_47_app__ = function () { return 'id'; } }; + this.isCompactView = function () { + return SettingsResource.get('compact'); + }; this.getRelativeDate = function (timestamp) { console.log(timestamp); }; + this.autoPage = function () { + console.log('hi'); + }; + this.scrollRead = function (itemIds) { + console.log(itemIds); + }; } ]); app.controller('NavigationController', [ @@ -422,6 +435,9 @@ var $__build_47_app__ = function () { return this.values.filter(function (v) { return v.folderId === folderId; }); + }, + getById: function (feedId) { + return this.ids[$traceurRuntime.toProperty(feedId)]; } }, {}, Resource); return new FeedResource($http, BASE_URL); @@ -457,21 +473,9 @@ var $__build_47_app__ = function () { BASE_URL ]); this.starredCount = 0; - this.highestId = 0; - this.lowestId = 0; }; var $ItemResource = ItemResource; $traceurRuntime.createClass(ItemResource, { - add: function (obj) { - var id = obj[$traceurRuntime.toProperty(this.id)]; - if (this.highestId < id) { - this.highestId = id; - } - if (this.lowestId === 0 || this.lowestId > id) { - this.lowestId = id; - } - $traceurRuntime.superCall(this, $ItemResource.prototype, 'add', [obj]); - }, receive: function (value, channel) { switch (channel) { case 'newestItemId': @@ -509,6 +513,13 @@ var $__build_47_app__ = function () { data: { isStarred: isStarred } }); }, + toggleStar: function (itemId) { + if (this.get(itemId).starred) { + this.star(itemId, false); + } else { + this.star(itemId, true); + } + }, markItemRead: function (itemId) { var isRead = arguments[1] !== void 0 ? arguments[1] : true; this.get(itemId).unread = !isRead; @@ -547,19 +558,7 @@ var $__build_47_app__ = function () { } return this.http.post(this.BASE_URL + '/items/read'); }, - getHighestId: function () { - return this.highestId; - }, - getLowestId: function () { - return this.lowestId; - }, - keepUnread: function (itemId) { - this.get(itemId).keepUnread = true; - return this.markItemRead(itemId, false); - }, clear: function () { - this.highestId = 0; - this.lowestId = 0; $traceurRuntime.superCall(this, $ItemResource.prototype, 'clear', []); } }, {}, Resource); diff --git a/js/controller/ContentController.js b/js/controller/ContentController.js index e1beff98d..164fa8662 100644 --- a/js/controller/ContentController.js +++ b/js/controller/ContentController.js @@ -20,25 +20,29 @@ function (Publisher, FeedResource, ItemResource, SettingsResource, data) { return ItemResource.getAll(); }; - // TBD this.toggleStar = (itemId) => { - console.log(itemId); + ItemResource.toggleStar(itemId); }; this.markRead = (itemId) => { - console.log(itemId); + ItemResource.markItemRead(itemId); + + let item = ItemResource.get(itemId); + FeedResource.markItemOfFeedRead(item.feedId); }; this.getFeed = (feedId) => { - console.log(feedId); + return FeedResource.getById(feedId); }; - this.keepUnread = (itemId) => { - console.log(itemId); - }; + this.toggleKeepUnread = (itemId) => { + let item = ItemResource.get(itemId); + if (!item.unread) { + FeedResource.markItemOfFeedUnread(item.feedId); + ItemResource.markItemRead(itemId, false); + } - this.isContentView = () => { - console.log('tbd'); + item.keepUnread = !item.keepUnread; }; this.orderBy = () => { @@ -49,7 +53,21 @@ function (Publisher, FeedResource, ItemResource, SettingsResource, data) { } }; + this.isCompactView = () => { + return SettingsResource.get('compact'); + }; + + // TBD this.getRelativeDate = (timestamp) => { console.log(timestamp); }; + + this.autoPage = () => { + console.log('hi'); + }; + + this.scrollRead = (itemIds) => { + console.log(itemIds); + }; + });
\ No newline at end of file diff --git a/js/service/FeedResource.js b/js/service/FeedResource.js index 3e7a2e8bd..135601b2f 100644 --- a/js/service/FeedResource.js +++ b/js/service/FeedResource.js @@ -109,7 +109,9 @@ app.factory('FeedResource', (Resource, $http, BASE_URL) => { return this.values.filter(v => v.folderId === folderId); } - + getById (feedId) { + return this.ids[feedId]; + } } return new FeedResource($http, BASE_URL); diff --git a/js/service/ItemResource.js b/js/service/ItemResource.js index 983b9b39a..625f58b5e 100644 --- a/js/service/ItemResource.js +++ b/js/service/ItemResource.js @@ -16,23 +16,6 @@ app.factory('ItemResource', (Resource, $http, BASE_URL) => { constructor ($http, BASE_URL) { super($http, BASE_URL); this.starredCount = 0; - this.highestId = 0; - this.lowestId = 0; - } - - - add (obj) { - let id = obj[this.id]; - - if (this.highestId < id) { - this.highestId = id; - } - - if (this.lowestId === 0 || this.lowestId > id) { - this.lowestId = id; - } - - super.add(obj); } @@ -84,6 +67,15 @@ app.factory('ItemResource', (Resource, $http, BASE_URL) => { } + toggleStar (itemId) { + if (this.get(itemId).starred) { + this.star(itemId, false); + } else { + this.star(itemId, true); + } + } + + markItemRead (itemId, isRead=true) { this.get(itemId).unread = !isRead; return this.http({ @@ -112,25 +104,7 @@ app.factory('ItemResource', (Resource, $http, BASE_URL) => { } - getHighestId () { - return this.highestId; - } - - - getLowestId () { - return this.lowestId; - } - - - keepUnread (itemId) { - this.get(itemId).keepUnread = true; - return this.markItemRead(itemId, false); - } - - clear () { - this.highestId = 0; - this.lowestId = 0; super.clear(); } diff --git a/js/tests/unit/controller/ContentControllerSpec.js b/js/tests/unit/controller/ContentControllerSpec.js index ac7c6f1a8..658ae9252 100644 --- a/js/tests/unit/controller/ContentControllerSpec.js +++ b/js/tests/unit/controller/ContentControllerSpec.js @@ -63,4 +63,126 @@ describe('ContentController', () => { expect(ctrl.orderBy()).toBe('-id'); })); + + it('should mark read', inject(($controller, + ItemResource, FeedResource, Publisher) => { + + Publisher.subscribe(ItemResource).toChannels('items'); + ItemResource.markItemRead = jasmine.createSpy('markRead'); + FeedResource.markItemOfFeedRead = jasmine.createSpy('markRead'); + + let ctrl = $controller('ContentController', { + ItemResource: ItemResource, + FeedResource: FeedResource, + |