added import from google reader, fix #80

This commit is contained in:
Bernhard Posselt 2013-04-22 18:24:31 +02:00
Родитель 366c1b1554
Коммит df18314b32
12 изменённых файлов: 382 добавлений и 51 удалений

Просмотреть файл

@ -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>

Просмотреть файл

@ -1 +1 @@
8.3
8.4

Просмотреть файл

@ -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);
// 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);
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: 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;
}

Просмотреть файл

@ -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();
});

Просмотреть файл

@ -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,

Просмотреть файл

@ -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

Просмотреть файл

@ -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);
};

Просмотреть файл

@ -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)
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)

Просмотреть файл

@ -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',

Просмотреть файл

@ -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);
}
}

Просмотреть файл

@ -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);
}
}

70
utility/importparser.php Normal file
Просмотреть файл

@ -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;
}
}