summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBernhard Posselt <nukeawhale@gmail.com>2013-04-22 18:24:31 +0200
committerBernhard Posselt <nukeawhale@gmail.com>2013-04-22 18:24:31 +0200
commitdf18314b32b05f10720936831ed43573e1792ae6 (patch)
treea2b8e28e165727e7a88d7ac3529f64d5f6b938e2
parent366c1b15545b4da69bc8e236ba4350c28ad24e77 (diff)
added import from google reader, fix #80
-rw-r--r--appinfo/database.xml2
-rw-r--r--appinfo/version2
-rw-r--r--businesslayer/feedbusinesslayer.php54
-rw-r--r--dependencyinjection/dicontainer.php44
-rw-r--r--js/app/services/businesslayer/feedbusinesslayer.coffee8
-rw-r--r--js/app/services/persistence.coffee3
-rw-r--r--js/public/app.js16
-rw-r--r--js/tests/services/businesslayer/feedbusinesslayerSpec.coffee19
-rw-r--r--js/tests/services/persistenceSpec.coffee3
-rw-r--r--tests/unit/businesslayer/FeedBusinessLayerTest.php102
-rw-r--r--tests/unit/utility/ImportParserTest.php114
-rw-r--r--utility/importparser.php70
12 files changed, 384 insertions, 53 deletions
diff --git a/appinfo/database.xml b/appinfo/database.xml
index 3198b402d..af0073098 100644
--- a/appinfo/database.xml
+++ b/appinfo/database.xml
@@ -112,7 +112,7 @@
<notnull>true</notnull>
</field>
<field>
- <name>preventUpdate</name>
+ <name>prevent_update</name>
<type>boolean</type>
<default>false</default>
<notnull>true</notnull>
diff --git a/appinfo/version b/appinfo/version
index 223a93930..fad030004 100644
--- a/appinfo/version
+++ b/appinfo/version
@@ -1 +1 @@
-8.3 \ No newline at end of file
+8.4 \ No newline at end of file
diff --git a/businesslayer/feedbusinesslayer.php b/businesslayer/feedbusinesslayer.php
index a543f352b..aba234989 100644
--- a/businesslayer/feedbusinesslayer.php
+++ b/businesslayer/feedbusinesslayer.php
@@ -34,6 +34,7 @@ use \OCA\News\Db\FeedMapper;
use \OCA\News\Db\ItemMapper;
use \OCA\News\Utility\Fetcher;
use \OCA\News\Utility\FetcherException;
+use \OCA\News\Utility\ImportParser;
class FeedBusinessLayer extends BusinessLayer {
@@ -41,15 +42,18 @@ class FeedBusinessLayer extends BusinessLayer {
private $itemMapper;
private $api;
private $timeFactory;
+ private $importParser;
public function __construct(FeedMapper $feedMapper, Fetcher $feedFetcher,
ItemMapper $itemMapper, API $api,
- TimeFactory $timeFactory){
+ TimeFactory $timeFactory,
+ ImportParser $importParser){
parent::__construct($feedMapper);
$this->feedFetcher = $feedFetcher;
$this->itemMapper = $itemMapper;
$this->api = $api;
$this->timeFactory = $timeFactory;
+ $this->importParser = $importParser;
}
@@ -190,28 +194,34 @@ class FeedBusinessLayer extends BusinessLayer {
*/
public function importGoogleReaderJSON($json, $userId) {
$url = 'http://owncloud/googlereader';
+ $urlHash = md5($url);
+
+ try {
+ $feed = $this->mapper->findByUrlHash($urlHash, $userId);
+ } catch(DoesNotExistException $ex) {
+ $feed = new Feed();
+ $feed->setUserId($userId);
+ $feed->setUrlHash($urlHash);
+ $feed->setUrl($url);
+ $feed->setTitle('Google Reader');
+ $feed->setAdded($this->timeFactory->getTime());
+ $feed->setFolderId(0);
+ $feed->setPreventUpdate(true);
+ $feed = $this->mapper->insert($feed);
+ }
+
+ foreach($this->importParser->parse($json) as $item) {
+ $item->setFeedId($feed->getId());
+ try {
+ $this->itemMapper->findByGuidHash(
+ $item->getGuidHash(), $item->getFeedId(), $userId);
+ } catch(DoesNotExistException $ex) {
+ $this->itemMapper->insert($item);
+ }
+ }
+
+ return $this->mapper->findByUrlHash($urlHash, $userId);
- // TODO: write unittests that ensure that the correct
- // feed parameters are being returned
-
- // you need to check first if the feed exists and if it does
- // use that feed to add the items and to return
- // if this has not been saved, these are the values
- // that need to be set fyi
- $feed = new Feed();
- $feed->setUserId($userId);
- $feed->setUrlHash(md5($url));
- $feed->setUrl($url);
- $feed->setTitle('Google Reader');
- $feed->setAdded($this->timeFactory->getTime());
- $feed->setFolderId(0);
- $feed->setPreventUpdate(true);
-
-
- // TODO: after saving the above feed, query the feed from the
- // database to get the unreadCount (this is being set in the
- // sql query) see line 177
- return $feed;
}
diff --git a/dependencyinjection/dicontainer.php b/dependencyinjection/dicontainer.php
index a4202e12c..27dae1f7b 100644
--- a/dependencyinjection/dicontainer.php
+++ b/dependencyinjection/dicontainer.php
@@ -25,28 +25,29 @@
namespace OCA\News\DependencyInjection;
-use OCA\AppFramework\DependencyInjection\DIContainer as BaseContainer;
+use \OCA\AppFramework\DependencyInjection\DIContainer as BaseContainer;
-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\UserSettingsController;
+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\UserSettingsController;
-use OCA\News\BusinessLayer\FolderBusinessLayer;
-use OCA\News\BusinessLayer\FeedBusinessLayer;
-use OCA\News\BusinessLayer\ItemBusinessLayer;
+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\FolderMapper;
+use \OCA\News\Db\FeedMapper;
+use \OCA\News\Db\ItemMapper;
+use \OCA\News\Db\StatusFlag;
-use OCA\News\Utility\Fetcher;
-use OCA\News\Utility\FeedFetcher;
-use OCA\News\Utility\TwitterFetcher;
-use OCA\News\Utility\OPMLExporter;
+use \OCA\News\Utility\Fetcher;
+use \OCA\News\Utility\FeedFetcher;
+use \OCA\News\Utility\TwitterFetcher;
+use \OCA\News\Utility\OPMLExporter;
+use \OCA\News\Utility\ImportParser;
class DIContainer extends BaseContainer {
@@ -111,7 +112,8 @@ class DIContainer extends BaseContainer {
$this['FeedBusinessLayer'] = $this->share(function($c){
return new FeedBusinessLayer($c['FeedMapper'], $c['Fetcher'],
- $c['ItemMapper'], $c['API'], $c['TimeFactory']);
+ $c['ItemMapper'], $c['API'], $c['TimeFactory'],
+ $c['ImportParser']);
});
$this['ItemBusinessLayer'] = $this->share(function($c){
@@ -164,6 +166,10 @@ class DIContainer extends BaseContainer {
return new TwitterFetcher($c['FeedFetcher']);
});
+ $this['ImportParser'] = $this->share(function($c){
+ return new ImportParser($c['TimeFactory']);
+ });
+
$this['StatusFlag'] = $this->share(function($c){
return new StatusFlag();
});
diff --git a/js/app/services/businesslayer/feedbusinesslayer.coffee b/js/app/services/businesslayer/feedbusinesslayer.coffee
index 93f89ad31..9a23bec43 100644
--- a/js/app/services/businesslayer/feedbusinesslayer.coffee
+++ b/js/app/services/businesslayer/feedbusinesslayer.coffee
@@ -188,8 +188,12 @@ FeedModel, NewLoading, _ExistsError, Utils, $rootScope, UndoQueue) ->
faviconLink: 'url('+@_utils.imagePath('core', 'loading.gif')+')'
@_feedModel.add(feed)
-
- @_persistence.importGoogleReader(json)
+
+ onSuccess = (response) =>
+ id = response.data.feeds[0].id
+ @load(id)
+
+ @_persistence.importGoogleReader(json, onSuccess)
return new FeedBusinessLayer(ShowAll, FeedModel, Persistence, ActiveFeed,
diff --git a/js/app/services/persistence.coffee b/js/app/services/persistence.coffee
index a5a6bc092..188f5a7c7 100644
--- a/js/app/services/persistence.coffee
+++ b/js/app/services/persistence.coffee
@@ -253,10 +253,11 @@ $rootScope) ->
@_request.post 'news_feeds_update', params
- importGoogleReader: (json) ->
+ importGoogleReader: (json, onSuccess) ->
params =
data:
json: json
+ onSuccess: onSuccess
@_request.post 'news_feeds_import_googlereader', params
diff --git a/js/public/app.js b/js/public/app.js
index ca7124ad7..f0c783ba1 100644
--- a/js/public/app.js
+++ b/js/public/app.js
@@ -961,7 +961,8 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
};
FeedBusinessLayer.prototype.importGoogleReader = function(json) {
- var feed, url;
+ var feed, onSuccess, url,
+ _this = this;
url = 'http://owncloud/googlereader';
if (angular.isUndefined(this._feedModel.getByUrl(url))) {
@@ -974,7 +975,13 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
};
this._feedModel.add(feed);
}
- return this._persistence.importGoogleReader(json);
+ onSuccess = function(response) {
+ var id;
+
+ id = response.data.feeds[0].id;
+ return _this.load(id);
+ };
+ return this._persistence.importGoogleReader(json, onSuccess);
};
return FeedBusinessLayer;
@@ -2617,13 +2624,14 @@ License along with this library. If not, see <http://www.gnu.org/licenses/>.
return this._request.post('news_feeds_update', params);
};
- Persistence.prototype.importGoogleReader = function(json) {
+ Persistence.prototype.importGoogleReader = function(json, onSuccess) {
var params;
params = {
data: {
json: json
- }
+ },
+ onSuccess: onSuccess
};
return this._request.post('news_feeds_import_googlereader', params);
};
diff --git a/js/tests/services/businesslayer/feedbusinesslayerSpec.coffee b/js/tests/services/businesslayer/feedbusinesslayerSpec.coffee
index 4f7e8f8b3..833af6da8 100644
--- a/js/tests/services/businesslayer/feedbusinesslayerSpec.coffee
+++ b/js/tests/services/businesslayer/feedbusinesslayerSpec.coffee
@@ -365,8 +365,25 @@ describe 'FeedBusinessLayer', ->
it 'should create an import google reader request', =>
+ returned =
+ data:
+ feeds: [
+ {id: 3, url: 'hi'}
+ ]
+ @persistence.getItems = jasmine.createSpy('importGoogleReader')
@persistence.importGoogleReader = jasmine.createSpy('importGoogleReader')
+ @persistence.importGoogleReader.andCallFake (data, onSuccess) =>
+ @FeedModel.handle(returned.data.feeds)
+ onSuccess(returned)
+
json = {"test": "hi"}
@FeedBusinessLayer.importGoogleReader(json)
- expect(@persistence.importGoogleReader).toHaveBeenCalledWith(json) \ No newline at end of file
+ expect(@persistence.importGoogleReader).toHaveBeenCalledWith(json,
+ jasmine.any(Function))
+ expect(@persistence.getItems).toHaveBeenCalledWith(
+ @FeedType.Feed, returned.data.feeds[0].id, 0
+ )
+ expect(@ActiveFeed.getId()).toBe(returned.data.feeds[0].id)
+ expect(@ActiveFeed.getType()).toBe(@FeedType.Feed)
+
diff --git a/js/tests/services/persistenceSpec.coffee b/js/tests/services/persistenceSpec.coffee
index 70bcf824f..90bd82783 100644
--- a/js/tests/services/persistenceSpec.coffee
+++ b/js/tests/services/persistenceSpec.coffee
@@ -252,8 +252,9 @@ describe 'Persistence', ->
params =
data:
json: {"some": "json"}
+ onSuccess: ->
- @Persistence.importGoogleReader(params.data.json)
+ @Persistence.importGoogleReader(params.data.json, params.onSuccess)
expect(@req.post).toHaveBeenCalledWith('news_feeds_import_googlereader',
diff --git a/tests/unit/businesslayer/FeedBusinessLayerTest.php b/tests/unit/businesslayer/FeedBusinessLayerTest.php
index cd044161f..0f8f61e4f 100644
--- a/tests/unit/businesslayer/FeedBusinessLayerTest.php
+++ b/tests/unit/businesslayer/FeedBusinessLayerTest.php
@@ -34,6 +34,7 @@ use \OCA\News\Db\Feed;
use \OCA\News\Db\Item;
use \OCA\News\Utility\Fetcher;
use \OCA\News\Utility\FetcherException;
+use \OCA\News\Utility\ImportParser;
class FeedBusinessLayerTest extends \OCA\AppFramework\Utility\TestUtility {
@@ -45,6 +46,7 @@ class FeedBusinessLayerTest extends \OCA\AppFramework\Utility\TestUtility {
private $itemMapper;
private $threshold;
private $time;
+ private $importParser;
protected function setUp(){
$this->api = $this->getAPIMock();
@@ -65,9 +67,12 @@ class FeedBusinessLayerTest extends \OCA\AppFramework\Utility\TestUtility {
$this->itemMapper = $this->getMockBuilder('\OCA\News\Db\ItemMapper')
->disableOriginalConstructor()
->getMock();
+ $this->importParser = $this->getMockBuilder('\OCA\News\Utility\ImportParser')
+ ->disableOriginalConstructor()
+ ->getMock();
$this->businessLayer = new FeedBusinessLayer($this->mapper,
$this->fetcher, $this->itemMapper, $this->api,
- $timeFactory);
+ $timeFactory, $this->importParser);
$this->user = 'jack';
$response = 'hi';
}
@@ -576,5 +581,100 @@ class FeedBusinessLayerTest extends \OCA\AppFramework\Utility\TestUtility {
}
+ public function testImportGoogleReaderJSON(){
+ $url = 'http://owncloud/googlereader';
+ $urlHash = md5($url);
+
+ $feed = new Feed();
+ $feed->setId(3);
+ $feed->setUserId($this->user);
+ $feed->setUrlHash($urlHash);
+ $feed->setUrl($url);
+ $feed->setTitle('Google Reader');
+ $feed->setAdded($this->time);
+ $feed->setFolderId(0);
+ $feed->setPreventUpdate(true);
+
+ $items = array(new Item());
+
+ $this->mapper->expects($this->at(0))
+ ->method('findByUrlHash')
+ ->with($this->equalTo($urlHash),
+ $this->equalTo($this->user))
+ ->will($this->throwException(new DoesNotExistException('hi')));
+ $this->mapper->expects($this->at(1))
+ ->method('insert')
+ ->will($this->returnValue($feed));
+ $this->mapper->expects($this->at(2))
+ ->method('findByUrlHash')
+ ->with($this->equalTo($urlHash),
+ $this->equalTo($this->user))
+ ->will($this->returnValue($feed));
+ $this->importParser->expects($this->once())
+ ->method('parse')
+ ->will($this->returnValue($items));
+ $this->itemMapper->expects($this->once())
+ ->method('findByGuidHash');
+ $this->itemMapper->expects($this->never())
+ ->method('insert');
+
+
+ $result = $this->businessLayer->importGoogleReaderJSON(array(), $this->user);
+
+ $this->assertEquals($feed, $result);
+ }
+
+
+ public function testImportGoogleReaderJSONFeedExists(){
+ $url = 'http://owncloud/googlereader';
+ $urlHash = md5($url);
+
+ $feed = new Feed();
+ $feed->setUserId($this->user);
+ $feed->setUrlHash($urlHash);
+ $feed->setUrl($url);
+ $feed->setTitle('Google Reader');
+ $feed->setAdded($this->time);
+ $feed->setFolderId(0);
+ $feed->setPreventUpdate(true);
+ $feed->setId(3);
+
+ $item = new Item();
+ $item->setGuidHash('hi');
+ $items = array($item);
+ $savedItem = new Item();
+ $savedItem->setFeedId($feed->getId());
+ $savedItem->setGuidHash('hi');
+
+ $in = array();
+
+ $this->mapper->expects($this->at(0))
+ ->method('findByUrlHash')
+ ->with($this->equalTo($urlHash),
+ $this->equalTo($this->user))
+ ->will($this->returnValue($feed));
+ $this->mapper->expects($this->at(1))
+ ->method('findByUrlHash')
+ ->with($this->equalTo($urlHash),
+ $this->equalTo($this->user))
+ ->will($this->returnValue($feed));
+ $this->importParser->expects($this->once())
+ ->method('parse')
+ ->with($this->equalTo($in))
+ ->will($this->returnValue($items));
+ $this->itemMapper->expects($this->once())
+ ->method('findByGuidHash')
+ ->with($this->equalTo($savedItem->getGuidHash()),
+ $this->equalTo($savedItem->getFeedId()),
+ $this->equalTo($this->user))
+ ->will($this->throwException(new DoesNotExistException('ho')));
+ $this->itemMapper->expects($this->once())
+ ->method('insert')
+ ->with($this->equalTo($savedItem));
+
+ $result = $this->businessLayer->importGoogleReaderJSON($in, $this->user);
+
+ $this->assertEquals($feed, $result);
+ }
}
diff --git a/tests/unit/utility/ImportParserTest.php b/tests/unit/utility/ImportParserTest.php
new file mode 100644
index 000000000..5c4a6292c
--- /dev/null
+++ b/tests/unit/utility/ImportParserTest.php
@@ -0,0 +1,114 @@
+<?php
+
+/**
+* ownCloud - News
+*
+* @author Alessandro Cosentino
+* @author Bernhard Posselt
+* @copyright 2012 Alessandro Cosentino cosenal@gmail.com
+* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the License, or any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+namespace OCA\News\Utility;
+
+use \OCA\News\Db\Item;
+
+require_once(__DIR__ . "/../../classloader.php");
+
+
+class ImportParserTest extends \OCA\AppFramework\Utility\TestUtility {
+
+ private $parser;
+ private $time;
+ private $in;
+
+ protected function setUp(){
+ $this->time = 222;
+ $timeFactory = $this->getMockBuilder(
+ '\OCA\AppFramework\Utility\TimeFactory')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $timeFactory->expects($this->any())
+ ->method('getTime')
+ ->will($this->returnValue($this->time));
+
+ $this->parser = new ImportParser($timeFactory);
+ $this->in = array(
+ 'items' => array(
+ array(
+ 'id' => "tag:google.com,2005:reader/item/f9fd1dd3c19262e1",
+ 'title' => "[HorribleSubs] Mushibugyo - 01 [720p].mkv",
+ "published" => 1365415485,
+
+ "alternate" => array( array(
+ "href" => "http://www.nyaa.eu/?page=view&tid=421561",
+ "type" => "text/html"
+ )),
+ "summary" => array(
+ "content" => "1596 seeder(s), 775 leecher(s), 8005 download(s) - 316.7 MiB - Trusted"
+ )
+ )
+ )
+ );
+ }
+
+
+ public function testImportParserReturnsEmptyArrayIfNoInput(){
+ $result = $this->parser->parse(array());
+
+ $this->assertEquals($result, array());
+ }
+
+
+ public function testParsesItems() {
+ $result = $this->parser->parse($this->in);
+
+ $out = new Item();
+ $out->setTitle($this->in['items'][0]['title']);
+ $out->setPubDate($this->in['items'][0]['published']);
+ $out->setBody($this->in['items'][0]['summary']['content']);
+ $out->setUrl($this->in['items'][0]['alternate'][0]['href']);
+ $out->setGuid($this->in['items'][0]['id']);
+ $out->setGuidHash(md5($this->in['items'][0]['id']));
+ $out->setStatus(0);
+ $out->setUnread();
+ $out->setStarred();
+
+ $this->assertEquals(array($out), $result);
+ }
+
+
+ public function testParsesItemsNoSummary() {
+ $this->in['items'][0]['content']['content'] = 'hi';
+ unset($this->in['items'][0]['summary']);
+ $result = $this->parser->parse($this->in);
+
+ $out = new Item();
+ $out->setTitle($this->in['items'][0]['title']);
+ $out->setPubDate($this->in['items'][0]['published']);
+ $out->setBody($this->in['items'][0]['content']['content']);
+ $out->setUrl($this->in['items'][0]['alternate'][0]['href']);
+ $out->setGuid($this->in['items'][0]['id']);
+ $out->setGuidHash(md5($this->in['items'][0]['id']));
+ $out->setStatus(0);
+ $out->setUnread();
+ $out->setStarred();
+
+ $this->assertEquals(array($out), $result);
+ }
+
+}
diff --git a/utility/importparser.php b/utility/importparser.php
new file mode 100644
index 000000000..acf52381c
--- /dev/null
+++ b/utility/importparser.php
@@ -0,0 +1,70 @@
+<?php
+
+/**
+* ownCloud - News
+*
+* @author Alessandro Cosentino
+* @author Bernhard Posselt
+* @copyright 2012 Alessandro Cosentino cosenal@gmail.com
+* @copyright 2012 Bernhard Posselt nukeawhale@gmail.com
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
+* License as published by the Free Software Foundation; either
+* version 3 of the License, or any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+*
+* You should have received a copy of the GNU Affero General Public
+* License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+namespace OCA\News\Utility;
+
+use \OCA\AppFramework\Utility\TimeFactory;
+
+use \OCA\News\Db\Item;
+
+
+class ImportParser {
+
+ private $timeFactory;
+
+ public function __construct(TimeFactory $timeFactory) {
+ $this->timeFactor = $timeFactory;
+ }
+
+ public function parse($json){
+ $items = array();
+
+ if(array_key_exists('items', $json)) {
+ foreach($json['items'] as $entry) {
+ $item = new Item();
+ $id = $entry['id'];
+ $item->setGuid($id);
+ $item->setGuidHash(md5($id));
+ $item->setTitle($entry['title']);
+ $item->setPubDate($entry['published']);
+ if(array_key_exists('summary', $entry)) {
+ $item->setBody($entry['summary']['content']);
+ } elseif(array_key_exists('content', $entry)) {
+ $item->setBody($entry['content']['content']);
+ }
+
+ $item->setUrl($entry['alternate'][0]['href']);
+ $item->setStatus(0);
+ $item->setStarred();
+ $item->setUnread();
+
+ array_push($items, $item);
+ }
+ }
+
+ return $items;
+ }
+
+}