diff options
-rw-r--r-- | db/itemmapper.php | 16 | ||||
-rw-r--r-- | js/app/controllers/feedcontroller.coffee | 13 | ||||
-rw-r--r-- | js/app/controllers/itemcontroller.coffee | 2 | ||||
-rw-r--r-- | js/app/services/businesslayer/feedbusinesslayer.coffee | 7 | ||||
-rw-r--r-- | js/app/services/persistence.coffee | 2 | ||||
-rw-r--r-- | js/public/app.js | 19 | ||||
-rw-r--r-- | js/tests/services/businesslayer/feedbusinesslayerSpec.coffee | 16 | ||||
-rw-r--r-- | tests/unit/db/ItemMapperTest.php | 13 | ||||
-rw-r--r-- | utility/feedfetcher.php | 6 |
9 files changed, 75 insertions, 19 deletions
diff --git a/db/itemmapper.php b/db/itemmapper.php index bffab6348..326d58a2d 100644 --- a/db/itemmapper.php +++ b/db/itemmapper.php @@ -115,16 +115,26 @@ class ItemMapper extends Mapper implements IMapper { public function readFeed($feedId, $highestItemId, $userId){ + // its 0 when the feed was not loaded or the loaded feed + // does not contain any items + if($highestItemId !== 0){ + $params = array(~StatusFlag::UNREAD, $feedId, $highestItemId, $userId, + $feedId); + $lowerSql = 'AND `id` <= ? '; + } else { + $lowerSql = ''; + $params = array(~StatusFlag::UNREAD, $feedId, $userId, $feedId); + } + $sql = 'UPDATE `*PREFIX*news_items` ' . 'SET `status` = `status` & ? ' . 'WHERE `feed_id` = ? ' . - 'AND `id` <= ? ' . + $lowerSql . 'AND EXISTS (' . 'SELECT * FROM `*PREFIX*news_feeds` ' . 'WHERE `user_id` = ? ' . 'AND `id` = ? ) '; - $params = array(~StatusFlag::UNREAD, $feedId, $highestItemId, $userId, - $feedId); + $this->execute($sql, $params); } diff --git a/js/app/controllers/feedcontroller.coffee b/js/app/controllers/feedcontroller.coffee index 3d8755cad..88a5d1c88 100644 --- a/js/app/controllers/feedcontroller.coffee +++ b/js/app/controllers/feedcontroller.coffee @@ -24,16 +24,18 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. angular.module('News').controller 'FeedController', ['$scope', '_ExistsError', 'Persistence', 'FolderBusinessLayer', 'FeedBusinessLayer', 'SubscriptionsBusinessLayer', 'StarredBusinessLayer', -'unreadCountFormatter', +'unreadCountFormatter', 'ActiveFeed', 'FeedType', ($scope, _ExistsError, Persistence, FolderBusinessLayer, FeedBusinessLayer, -SubscriptionsBusinessLayer, StarredBusinessLayer, unreadCountFormatter) -> +SubscriptionsBusinessLayer, StarredBusinessLayer, unreadCountFormatter, +ActiveFeed, FeedType) -> class FeedController constructor: (@_$scope, @_persistence, @_folderBusinessLayer, @_feedBusinessLayer, @_subscriptionsBusinessLayer, - @_starredBusinessLayer, @_unreadCountFormatter) -> + @_starredBusinessLayer, @_unreadCountFormatter, + @_activeFeed, @_feedType) -> @_isAddingFolder = false @_isAddingFeed = false @@ -45,7 +47,6 @@ SubscriptionsBusinessLayer, StarredBusinessLayer, unreadCountFormatter) -> @_$scope.starredBusinessLayer = @_starredBusinessLayer @_$scope.unreadCountFormatter = @_unreadCountFormatter - @_$scope.isAddingFolder = => return @_isAddingFolder @@ -111,8 +112,10 @@ SubscriptionsBusinessLayer, StarredBusinessLayer, unreadCountFormatter) -> @_feedBusinessLayer.move(data.feedId, data.folderId) + return new FeedController($scope, Persistence, FolderBusinessLayer, FeedBusinessLayer, SubscriptionsBusinessLayer, - StarredBusinessLayer, unreadCountFormatter) + StarredBusinessLayer, unreadCountFormatter, + ActiveFeed, FeedType) ]
\ No newline at end of file diff --git a/js/app/controllers/itemcontroller.coffee b/js/app/controllers/itemcontroller.coffee index fb5b5bfa3..d803ad484 100644 --- a/js/app/controllers/itemcontroller.coffee +++ b/js/app/controllers/itemcontroller.coffee @@ -66,7 +66,7 @@ Language, AutoPageLoading) -> if @_autoPaging # prevent multiple autopaging requests @_autoPaging = false - @_itemBusinessLayer.loadNext => + @_itemBusinessLayer.loadNext (data) => @_autoPaging = true diff --git a/js/app/services/businesslayer/feedbusinesslayer.coffee b/js/app/services/businesslayer/feedbusinesslayer.coffee index fcdcc8093..a5176452e 100644 --- a/js/app/services/businesslayer/feedbusinesslayer.coffee +++ b/js/app/services/businesslayer/feedbusinesslayer.coffee @@ -32,6 +32,7 @@ FeedModel, NewLoading, _ExistsError, Utils) -> constructor: (@_showAll, @_feedModel, persistence, activeFeed, feedType, itemModel, @_newLoading, @_utils) -> super(activeFeed, persistence, itemModel, feedType.Feed) + @_feedType = feedType getUnreadCount: (feedId) -> @@ -59,7 +60,11 @@ FeedModel, NewLoading, _ExistsError, Utils) -> feed = @_feedModel.getById(feedId) if angular.isDefined(feed) feed.unreadCount = 0 - highestItemId = @_itemModel.getHighestId() + if @_activeFeed.getId() == feedId and + @_activeFeed.getType() == @_feedType.Feed + highestItemId = @_itemModel.getHighestId() + else + highestItemId = 0 @_persistence.setFeedRead(feedId, highestItemId) for item in @_itemModel.getAll() item.setRead() diff --git a/js/app/services/persistence.coffee b/js/app/services/persistence.coffee index 4c4ceb370..06945f433 100644 --- a/js/app/services/persistence.coffee +++ b/js/app/services/persistence.coffee @@ -63,7 +63,7 @@ $rootScope) -> # loading sign handling loading.increase() successCallbackWrapper = (data) => - onSuccess() + onSuccess(data) loading.decrease() failureCallbackWrapper = (data) => loading.decrease() diff --git a/js/public/app.js b/js/public/app.js index 603600810..624c4575d 100644 --- a/js/public/app.js +++ b/js/public/app.js @@ -314,11 +314,11 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. (function() { angular.module('News').controller('FeedController', [ - '$scope', '_ExistsError', 'Persistence', 'FolderBusinessLayer', 'FeedBusinessLayer', 'SubscriptionsBusinessLayer', 'StarredBusinessLayer', 'unreadCountFormatter', function($scope, _ExistsError, Persistence, FolderBusinessLayer, FeedBusinessLayer, SubscriptionsBusinessLayer, StarredBusinessLayer, unreadCountFormatter) { + '$scope', '_ExistsError', 'Persistence', 'FolderBusinessLayer', 'FeedBusinessLayer', 'SubscriptionsBusinessLayer', 'StarredBusinessLayer', 'unreadCountFormatter', 'ActiveFeed', 'FeedType', function($scope, _ExistsError, Persistence, FolderBusinessLayer, FeedBusinessLayer, SubscriptionsBusinessLayer, StarredBusinessLayer, unreadCountFormatter, ActiveFeed, FeedType) { var FeedController; FeedController = (function() { - function FeedController(_$scope, _persistence, _folderBusinessLayer, _feedBusinessLayer, _subscriptionsBusinessLayer, _starredBusinessLayer, _unreadCountFormatter) { + function FeedController(_$scope, _persistence, _folderBusinessLayer, _feedBusinessLayer, _subscriptionsBusinessLayer, _starredBusinessLayer, _unreadCountFormatter, _activeFeed, _feedType) { var _this = this; this._$scope = _$scope; @@ -328,6 +328,8 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. this._subscriptionsBusinessLayer = _subscriptionsBusinessLayer; this._starredBusinessLayer = _starredBusinessLayer; this._unreadCountFormatter = _unreadCountFormatter; + this._activeFeed = _activeFeed; + this._feedType = _feedType; this._isAddingFolder = false; this._isAddingFeed = false; this._$scope.folderBusinessLayer = this._folderBusinessLayer; @@ -408,7 +410,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. return FeedController; })(); - return new FeedController($scope, Persistence, FolderBusinessLayer, FeedBusinessLayer, SubscriptionsBusinessLayer, StarredBusinessLayer, unreadCountFormatter); + return new FeedController($scope, Persistence, FolderBusinessLayer, FeedBusinessLayer, SubscriptionsBusinessLayer, StarredBusinessLayer, unreadCountFormatter, ActiveFeed, FeedType); } ]); @@ -485,7 +487,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. this._$scope.$on('autoPage', function() { if (_this._autoPaging) { _this._autoPaging = false; - return _this._itemBusinessLayer.loadNext(function() { + return _this._itemBusinessLayer.loadNext(function(data) { return _this._autoPaging = true; }); } @@ -701,6 +703,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. this._newLoading = _newLoading; this._utils = _utils; FeedBusinessLayer.__super__.constructor.call(this, activeFeed, persistence, itemModel, feedType.Feed); + this._feedType = feedType; } FeedBusinessLayer.prototype.getUnreadCount = function(feedId) { @@ -730,7 +733,11 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. feed = this._feedModel.getById(feedId); if (angular.isDefined(feed)) { feed.unreadCount = 0; - highestItemId = this._itemModel.getHighestId(); + if (this._activeFeed.getId() === feedId && this._activeFeed.getType() === this._feedType.Feed) { + highestItemId = this._itemModel.getHighestId(); + } else { + highestItemId = 0; + } this._persistence.setFeedRead(feedId, highestItemId); _ref = this._itemModel.getAll(); _results = []; @@ -2256,7 +2263,7 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>. } loading.increase(); successCallbackWrapper = function(data) { - onSuccess(); + onSuccess(data); return loading.decrease(); }; failureCallbackWrapper = function(data) { diff --git a/js/tests/services/businesslayer/feedbusinesslayerSpec.coffee b/js/tests/services/businesslayer/feedbusinesslayerSpec.coffee index 8e09e7be9..1b9f009d5 100644 --- a/js/tests/services/businesslayer/feedbusinesslayerSpec.coffee +++ b/js/tests/services/businesslayer/feedbusinesslayerSpec.coffee @@ -89,6 +89,7 @@ describe 'FeedBusinessLayer', -> it 'should mark feed as read', => + @ActiveFeed.handle({type: @FeedType.Feed, id: 5}) @persistence.setFeedRead = jasmine.createSpy('setFeedRead') @FeedModel.add({id: 5, unreadCount:2, folderId: 2, urlHash: 'a1'}) @ItemModel.add({id: 6, feedId: 5, guidHash: 'a1'}) @@ -103,6 +104,21 @@ describe 'FeedBusinessLayer', -> expect(@ItemModel.getById(2).isRead()).toBeTruthy() + it 'should mark feed as read and set 0 if as highest id if its not active',=> + @persistence.setFeedRead = jasmine.createSpy('setFeedRead') + @FeedModel.add({id: 5, unreadCount:2, folderId: 2, urlHash: 'a1'}) + @ItemModel.add({id: 6, feedId: 5, guidHash: 'a1'}) + @ItemModel.add({id: 3, feedId: 5, guidHash: 'a2'}) + @ItemModel.add({id: 2, feedId: 5, guidHash: 'a3'}) + @FeedBusinessLayer.markFeedRead(5) + + expect(@persistence.setFeedRead).toHaveBeenCalledWith(5, 0) + expect(@FeedModel.getById(5).unreadCount).toBe(0) + expect(@ItemModel.getById(6).isRead()).toBeTruthy() + expect(@ItemModel.getById(3).isRead()).toBeTruthy() + expect(@ItemModel.getById(2).isRead()).toBeTruthy() + + it 'should mark all as read', => @persistence.setFeedRead = jasmine.createSpy('setFeedRead') @FeedModel.add({id: 3, unreadCount:134, folderId: 3, urlHash: 'a1'}) diff --git a/tests/unit/db/ItemMapperTest.php b/tests/unit/db/ItemMapperTest.php index a7fead8f0..ed47f175c 100644 --- a/tests/unit/db/ItemMapperTest.php +++ b/tests/unit/db/ItemMapperTest.php @@ -132,6 +132,19 @@ class ItemMapperTest extends \OCA\AppFramework\Utility\MapperTestUtility { } + public function testReadFeedShouldMarkAllAsReadWhenIdZero(){ + $sql = 'UPDATE `*PREFIX*news_items` ' . + 'SET `status` = `status` & ? ' . + 'WHERE `feed_id` = ? ' . + 'AND EXISTS (' . + 'SELECT * FROM `*PREFIX*news_feeds` ' . + 'WHERE `user_id` = ? ' . + 'AND `id` = ? ) '; + $params = array(~StatusFlag::UNREAD, 3,$this->user, 3); + $this->setMapperResult($sql, $params); + $this->mapper->readFeed(3, 0, $this->user); + } + public function testFindAllNew(){ $sql = 'AND `items`.`id` >= ?'; $sql = $this->makeSelectQueryStatus($sql, $this->status); diff --git a/utility/feedfetcher.php b/utility/feedfetcher.php index e9950e7cd..f48839029 100644 --- a/utility/feedfetcher.php +++ b/utility/feedfetcher.php @@ -81,7 +81,8 @@ class FeedFetcher implements IFeedFetcher { $item->setStatus(0); $item->setUnread(); $item->setUrl( $feedItem->get_permalink() ); - $item->setTitle( $feedItem->get_title() ); + // unescape content because angularjs helps agains XSS + $item->setTitle(html_entity_decode($feedItem->get_title())); $item->setGuid( $feedItem->get_id() ); $item->setGuidHash( md5($feedItem->get_id()) ); $item->setBody( $feedItem->get_content() ); @@ -108,7 +109,8 @@ class FeedFetcher implements IFeedFetcher { } $feed = new Feed(); - $feed->setTitle($simplePie->get_title()); + // unescape content because angularjs helps agains XSS + $feed->setTitle(html_entity_decode($simplePie->get_title())); $feed->setUrl($url); $feed->setLink($simplePie->get_link()); $feed->setUrlHash(md5($url)); |