This commit is contained in:
Sean Molenaar 2019-02-23 16:11:28 +01:00
Родитель ee6bb6ce70
Коммит 7c17b2c24b
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: EB85127E18A6A2E5
6 изменённых файлов: 363 добавлений и 908 удалений

13
composer.lock сгенерированный
Просмотреть файл

@ -996,16 +996,16 @@
}, },
{ {
"name": "phpunit/phpunit", "name": "phpunit/phpunit",
"version": "6.5.13", "version": "6.5.14",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git", "url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "0973426fb012359b2f18d3bd1e90ef1172839693" "reference": "bac23fe7ff13dbdb461481f706f0e9fe746334b7"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0973426fb012359b2f18d3bd1e90ef1172839693", "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/bac23fe7ff13dbdb461481f706f0e9fe746334b7",
"reference": "0973426fb012359b2f18d3bd1e90ef1172839693", "reference": "bac23fe7ff13dbdb461481f706f0e9fe746334b7",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -1076,7 +1076,7 @@
"testing", "testing",
"xunit" "xunit"
], ],
"time": "2018-09-08T15:10:43+00:00" "time": "2019-02-01T05:22:47+00:00"
}, },
{ {
"name": "phpunit/phpunit-mock-objects", "name": "phpunit/phpunit-mock-objects",
@ -1135,6 +1135,7 @@
"mock", "mock",
"xunit" "xunit"
], ],
"abandoned": true,
"time": "2018-08-09T05:50:03+00:00" "time": "2018-08-09T05:50:03+00:00"
}, },
{ {
@ -1792,7 +1793,7 @@
}, },
{ {
"name": "Gert de Pagter", "name": "Gert de Pagter",
"email": "backendtea@gmail.com" "email": "BackEndTea@gmail.com"
} }
], ],
"description": "Symfony polyfill for ctype functions", "description": "Symfony polyfill for ctype functions",

876
js/package-lock.json сгенерированный

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@ -43,21 +43,23 @@
"gulp-uglify": "^2.0.0", "gulp-uglify": "^2.0.0",
"jasmine-core": "^2.99.1", "jasmine-core": "^2.99.1",
"jquery": "^2.2.4", "jquery": "^2.2.4",
"jshint": "^2.9.6", "jshint": "^2.10.1",
"karma": "^1.3.0", "karma": "^1.3.0",
"karma-chrome-launcher": "^2.0.0", "karma-chrome-launcher": "^2.0.0",
"karma-coverage": "^1.1.2", "karma-coverage": "^1.1.2",
"karma-firefox-launcher": "^1.0.0", "karma-firefox-launcher": "^1.0.0",
"karma-jasmine": "^1.1.2" "karma-jasmine": "^1.1.2",
"natives": "^1.1.6",
"minimatch": "^3.0.4"
}, },
"dependencies": { "dependencies": {
"angular": "^1.7.5", "angular": "^1.7.7",
"angular-animate": "^1.7.5", "angular-animate": "^1.7.7",
"angular-mocks": "^1.7.5", "angular-mocks": "^1.7.7",
"angular-route": "^1.7.5", "angular-route": "^1.7.7",
"angular-sanitize": "^1.7.5", "angular-sanitize": "^1.7.7",
"debug": "^2.6.8", "debug": "^2.6.8",
"masonry-layout": "^4.2.2", "masonry-layout": "^4.2.2",
"moment": "^2.22.2" "moment": "^2.24.0"
} }
} }

46
lib/Fetcher/FeedFetcher.php Normal file → Executable file
Просмотреть файл

@ -19,6 +19,7 @@ use FeedIo\Feed\ItemInterface;
use FeedIo\FeedInterface; use FeedIo\FeedInterface;
use FeedIo\FeedIo; use FeedIo\FeedIo;
use OCA\News\Utility\PsrLogger;
use OCP\IL10N; use OCP\IL10N;
use OCA\News\Db\Item; use OCA\News\Db\Item;
@ -32,13 +33,15 @@ class FeedFetcher implements IFeedFetcher
private $reader; private $reader;
private $l10n; private $l10n;
private $time; private $time;
private $logger;
public function __construct(FeedIo $fetcher, Favicon $favicon, IL10N $l10n, Time $time) public function __construct(FeedIo $fetcher, Favicon $favicon, IL10N $l10n, Time $time, PsrLogger $logger)
{ {
$this->reader = $fetcher; $this->reader = $fetcher;
$this->faviconFactory = $favicon; $this->faviconFactory = $favicon;
$this->l10n = $l10n; $this->l10n = $l10n;
$this->time = $time; $this->time = $time;
$this->logger = $logger;
} }
@ -62,14 +65,24 @@ class FeedFetcher implements IFeedFetcher
*/ */
public function fetch(string $url, bool $favicon, $lastModified, $user, $password): array public function fetch(string $url, bool $favicon, $lastModified, $user, $password): array
{ {
if ($user !== null && trim($user) !== '') { if (!empty($user) && !empty(trim($user))) {
$url = explode('://', $url); $url = explode('://', $url);
$url = $url[0] . '://' . $user . ':' . $password . '@' . $url[1]; $url = $url[0] . '://' . $user . ':' . $password . '@' . $url[1];
} }
$resource = $this->reader->readSince($url, new DateTime($lastModified)); if (is_null($lastModified) || !is_string($lastModified)) {
$resource = $this->reader->read($url);
} else {
$resource = $this->reader->readSince($url, new DateTime($lastModified));
}
if (!$resource->getResponse()->isModified()) { $response = $resource->getResponse();
throw new FetcherException('Feed was not modified since last fetch'); if (!$response->isModified()) {
$this->logger->debug('Feed {url} was not modified since last fetch. old: {old}, new: {new}', [
'url' => $url,
'old' => print_r($lastModified, true),
'new' => print_r($response->getLastModified(), true),
]);
return [null, []];
} }
$location = $resource->getUrl(); $location = $resource->getUrl();
@ -82,6 +95,7 @@ class FeedFetcher implements IFeedFetcher
); );
$items = []; $items = [];
$this->logger->debug('Feed ' . $url . ' was modified since last fetch. #' . count($parsedFeed) . ' items');
foreach ($parsedFeed as $item) { foreach ($parsedFeed as $item) {
$items[] = $this->buildItem($item, $parsedFeed); $items[] = $this->buildItem($item, $parsedFeed);
} }
@ -153,26 +167,32 @@ class FeedFetcher implements IFeedFetcher
$item->setUnread(true); $item->setUnread(true);
$item->setUrl($parsedItem->getLink()); $item->setUrl($parsedItem->getLink());
$item->setGuid($parsedItem->getPublicId()); $item->setGuid($parsedItem->getPublicId());
$item->setGuidHash($item->getGuid()); $item->setGuidHash(md5($item->getGuid()));
$pubDT = $parsedItem->getLastModified(); $lastmodified = $parsedItem->getLastModified() ?? new \DateTime();
if ($parsedItem->getValue('pubDate') !== null) { if ($parsedItem->getValue('pubDate') !== null) {
$pubDT = new DateTime($parsedItem->getValue('pubDate')); $pubDT = new DateTime($parsedItem->getValue('pubDate'));
} elseif ($parsedItem->getValue('published') !== null) { } elseif ($parsedItem->getValue('published') !== null) {
$pubDT = new DateTime($parsedItem->getValue('published')); $pubDT = new DateTime($parsedItem->getValue('published'));
} else {
$pubDT = $lastmodified;
} }
$item->setPubDate( $item->setPubDate(
$pubDT->getTimestamp() $pubDT->getTimestamp()
); );
$item->setLastModified( $item->setLastModified(
$parsedItem->getLastModified()->getTimestamp() $lastmodified->getTimestamp()
); );
$item->setRtl($this->determineRtl($parsedFeed)); $item->setRtl($this->determineRtl($parsedFeed));
// unescape content because angularjs helps against XSS // unescape content because angularjs helps against XSS
$item->setTitle($this->decodeTwice($parsedItem->getTitle())); $item->setTitle($this->decodeTwice($parsedItem->getTitle()));
$item->setAuthor($this->decodeTwice($parsedItem->getAuthor())); $author = $parsedItem->getAuthor();
if (!is_null($author)) {
$item->setAuthor($this->decodeTwice($author->getName()));
}
// purification is done in the service layer // purification is done in the service layer
$body = $parsedItem->getDescription(); $body = $parsedItem->getDescription();
@ -196,6 +216,11 @@ class FeedFetcher implements IFeedFetcher
$item->generateSearchIndex(); $item->generateSearchIndex();
$this->logger->debug('Added item {title} for feed {feed} publishdate: {datetime}', [
'title' => $item->getTitle(),
'feed' => $parsedFeed->getTitle(),
'datetime' => $item->getLastModified(),
]);
return $item; return $item;
} }
@ -219,7 +244,8 @@ class FeedFetcher implements IFeedFetcher
$newFeed->setUrl($url); // the url used to add the feed $newFeed->setUrl($url); // the url used to add the feed
$newFeed->setLocation($location); // the url where the feed was found $newFeed->setLocation($location); // the url where the feed was found
$newFeed->setLink($feed->getLink()); // <link> attribute in the feed $newFeed->setLink($feed->getLink()); // <link> attribute in the feed
$newFeed->setLastModified($feed->getLastModified()->getTimestamp()); $lastmodified = $feed->getLastModified() ?? new DateTime();
$newFeed->setLastModified($lastmodified->getTimestamp());
$newFeed->setAdded($this->time->getTime()); $newFeed->setAdded($this->time->getTime());
if (!$getFavicon) { if (!$getFavicon) {

3
package-lock.json сгенерированный Normal file
Просмотреть файл

@ -0,0 +1,3 @@
{
"lockfileVersion": 1
}

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

@ -13,13 +13,18 @@
namespace OCA\News\Tests\Unit\Fetcher; namespace OCA\News\Tests\Unit\Fetcher;
use FeedIo\Feed\Item\Author;
use FeedIo\Feed\Item\MediaInterface; use FeedIo\Feed\Item\MediaInterface;
use FeedIo\Feed\ItemInterface;
use FeedIo\FeedInterface;
use OC\L10N\L10N;
use OCA\AdminAudit\Actions\Auth;
use \OCA\News\Db\Feed; use \OCA\News\Db\Feed;
use \OCA\News\Db\Item; use \OCA\News\Db\Item;
use OCA\News\Fetcher\FeedFetcher; use OCA\News\Fetcher\FeedFetcher;
use OCA\News\Utility\PicoFeedFaviconFactory; use OCA\News\Utility\PicoFeedFaviconFactory;
use OCA\News\Utility\PsrLogger;
use OCA\News\Utility\Time; use OCA\News\Utility\Time;
use OCP\Http\Client\IClientService;
use OCP\IL10N; use OCP\IL10N;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
@ -41,150 +46,190 @@ class FeedFetcherTest extends TestCase
* *
* @var FeedFetcher * @var FeedFetcher
*/ */
private $_fetcher; private $fetcher;
/** /**
* Feed reader * Feed reader
* *
* @var \FeedIo\FeedIo * @var \FeedIo\FeedIo
*/ */
private $_reader; private $reader;
/** /**
* Feed reader result * Feed reader result
* *
* @var \FeedIo\Reader\Result * @var \FeedIo\Reader\Result
*/ */
private $_result; private $result;
/** /**
* Feed reader result object * Feed reader result object
* *
* @var \FeedIo\Adapter\ResponseInterface * @var \FeedIo\Adapter\ResponseInterface
*/ */
private $_response; private $response;
private $_favicon; /**
private $_l10n; * @var \Favicon\Favicon
private $_url; */
private $_time; private $favicon;
private $_item_mock;
private $_feed_mock; /**
private $_encoding; * @var L10N
*/
private $l10n;
/**
* @var ItemInterface
*/
private $item_mock;
/**
* @var FeedInterface
*/
private $feed_mock;
/**
* @var PsrLogger
*/
private $logger;
//metadata
/**
* @var integer
*/
private $time;
/**
* @var string
*/
private $encoding;
/**
* @var string
*/
private $url;
// items // items
private $_permalink; private $permalink;
private $_title; private $title;
private $_guid; private $guid;
private $_pub; private $guid_hash;
private $_updated; private $pub;
private $_body; private $updated;
private $_author; private $body;
private $_enclosure; /**
private $_rtl; * @var Author
private $_language; */
private $author;
private $enclosure;
private $rtl;
private $language;
// feed // feed
private $_feed_title; private $feed_title;
private $_feed_link; private $feed_link;
private $_feed_image; private $feed_image;
private $_web_favicon; private $web_favicon;
private $_modified; private $modified;
private $_location; private $location;
protected function setUp() protected function setUp()
{ {
$this->_l10n = $this->getMockBuilder(\OCP\IL10N::class) $this->l10n = $this->getMockBuilder(\OCP\IL10N::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->_reader = $this->getMockBuilder(\FeedIo\FeedIo::class) $this->reader = $this->getMockBuilder(\FeedIo\FeedIo::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->_favicon = $this->getMockBuilder(\Favicon\Favicon::class) $this->favicon = $this->getMockBuilder(\Favicon\Favicon::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->_result = $this->getMockBuilder(\FeedIo\Reader\Result::class) $this->result = $this->getMockBuilder(\FeedIo\Reader\Result::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->_response = $this->getMockBuilder(\FeedIo\Adapter\ResponseInterface::class) $this->response = $this->getMockBuilder(\FeedIo\Adapter\ResponseInterface::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->_item_mock = $this->getMockBuilder(\FeedIo\Feed\ItemInterface::class) $this->item_mock = $this->getMockBuilder(\FeedIo\Feed\ItemInterface::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->_feed_mock = $this->getMockBuilder(\FeedIo\FeedInterface::class) $this->feed_mock = $this->getMockBuilder(\FeedIo\FeedInterface::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->_time = 2323; $this->time = 2323;
$timeFactory = $this->getMockBuilder(\OCA\News\Utility\Time::class) $timeFactory = $this->getMockBuilder(\OCA\News\Utility\Time::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$timeFactory->expects($this->any()) $timeFactory->expects($this->any())
->method('getTime') ->method('getTime')
->will($this->returnValue($this->_time)); ->will($this->returnValue($this->time));
$clientService = $this->getMockBuilder(IClientService::class) $this->logger = $this->getMockBuilder(PsrLogger::class)
->disableOriginalConstructor()
->getMock(); ->getMock();
$this->_fetcher = new FeedFetcher( $this->fetcher = new FeedFetcher(
$this->_reader, $this->reader,
$this->_favicon, $this->favicon,
$this->_l10n, $this->l10n,
$timeFactory, $timeFactory,
$clientService $this->logger
); );
$this->_url = 'http://tests'; $this->url = 'http://tests';
$this->_permalink = 'http://permalink'; $this->permalink = 'http://permalink';
$this->_title = 'my&amp;lt;&apos; title'; $this->title = 'my&amp;lt;&apos; title';
$this->_guid = 'hey guid here'; $this->guid = 'hey guid here';
$this->_body = 'let the bodies hit the floor <a href="test">test</a>'; $this->guid_hash = 'df9a5f84e44bfe38cf44f6070d5b0250';
$this->_pub = 23111; $this->body = 'let the bodies hit the floor <a href="test">test</a>';
$this->_updated = 23444; $this->pub = 23111;
$this->_author = '&lt;boogieman'; $this->updated = 23444;
$this->_enclosure = 'http://enclosure.you'; $this->author = new Author();
$this->author->setName('&lt;boogieman');
$this->enclosure = 'http://enclosure.you';
$this->_feed_title = '&lt;a&gt;&amp;its a&lt;/a&gt; title'; $this->feed_title = '&lt;a&gt;&amp;its a&lt;/a&gt; title';
$this->_feed_link = 'http://tests'; $this->feed_link = 'http://tests';
$this->_feed_image = '/an/image'; $this->feed_image = '/an/image';
$this->_web_favicon = 'http://anon.google.com'; $this->web_favicon = 'http://anon.google.com';
$this->_modified = $this->getMockBuilder('\DateTime')->getMock(); $this->modified = $this->getMockBuilder('\DateTime')->getMock();
$this->_modified->expects($this->any()) $this->modified->expects($this->any())
->method('getTimestamp') ->method('getTimestamp')
->will($this->returnValue(3)); ->will($this->returnValue(3));
$this->_encoding = 'UTF-8'; $this->encoding = 'UTF-8';
$this->_language = 'de-DE'; $this->language = 'de-DE';
$this->_rtl = false; $this->rtl = false;
} }
public function testCanHandle() public function testCanHandle()
{ {
$url = 'google.de'; $url = 'google.de';
$this->assertTrue($this->_fetcher->canHandle($url)); $this->assertTrue($this->fetcher->canHandle($url));
} }
/** /**
* Test if error is thrown when the feed remain the same. * Test if empty is logged when the feed remain the same.
*
* @expectedException \OCA\News\Fetcher\FetcherException
* @expectedExceptionMessage Feed was not modified since last fetch
*/ */
public function testNoFetchIfNotModified() public function testNoFetchIfNotModified()
{ {
$this->_setUpReader($this->_url, false);; $this->__setUpReader($this->url, false);
$result = $this->_fetcher->fetch($this->_url, false, null, null, null); $this->logger->expects($this->once())
$this->assertSame([null, null], $result); ->method('debug')
->with('Feed {url} was not modified since last fetch. old: {old}, new: {new}');
$result = $this->fetcher->fetch($this->url, false, null, null, null);
$this->assertSame([null, []], $result);
} }
public function testFetch() public function testFetch()
{ {
$this->_setUpReader($this->_url); $this->__setUpReader($this->url);
$item = $this->_createItem(); $item = $this->_createItem();
$feed = $this->_createFeed(); $feed = $this->_createFeed();
$this->_mockIterator($this->_feed_mock, [$this->_item_mock]); $this->_mockIterator($this->feed_mock, [$this->item_mock]);
$result = $this->_fetcher->fetch($this->_url, false, null, null, null); $result = $this->fetcher->fetch($this->url, false, null, null, null);
$this->assertEquals([$feed, [$item]], $result); $this->assertEquals([$feed, [$item]], $result);
} }
@ -192,11 +237,11 @@ class FeedFetcherTest extends TestCase
public function testAudioEnclosure() public function testAudioEnclosure()
{ {
$this->_setUpReader($this->_url); $this->__setUpReader($this->url);
$item = $this->_createItem('audio/ogg'); $item = $this->_createItem('audio/ogg');
$feed = $this->_createFeed(); $feed = $this->_createFeed();
$this->_mockIterator($this->_feed_mock, [$this->_item_mock]); $this->_mockIterator($this->feed_mock, [$this->item_mock]);
$result = $this->_fetcher->fetch($this->_url, false, null, null, null); $result = $this->fetcher->fetch($this->url, false, null, null, null);
$this->assertEquals([$feed, [$item]], $result); $this->assertEquals([$feed, [$item]], $result);
} }
@ -204,60 +249,60 @@ class FeedFetcherTest extends TestCase
public function testVideoEnclosure() public function testVideoEnclosure()
{ {
$this->_setUpReader($this->_url); $this->__setUpReader($this->url);
$item = $this->_createItem('video/ogg'); $item = $this->_createItem('video/ogg');
$feed = $this->_createFeed(); $feed = $this->_createFeed();
$this->_mockIterator($this->_feed_mock, [$this->_item_mock]); $this->_mockIterator($this->feed_mock, [$this->item_mock]);
$result = $this->_fetcher->fetch($this->_url, false, null, null, null); $result = $this->fetcher->fetch($this->url, false, null, null, null);
$this->assertEquals([$feed, [$item]], $result); $this->assertEquals([$feed, [$item]], $result);
} }
public function testFavicon() public function testFavicon()
{ {
$this->_setUpReader($this->_url); $this->__setUpReader($this->url);
$feed = $this->_createFeed('de-DE', true); $feed = $this->_createFeed('de-DE', true);
$item = $this->_createItem(); $item = $this->_createItem();
$this->_mockIterator($this->_feed_mock, [$this->_item_mock]); $this->_mockIterator($this->feed_mock, [$this->item_mock]);
$result = $this->_fetcher->fetch($this->_url, true, null, null, null); $result = $this->fetcher->fetch($this->url, true, null, null, null);
$this->assertEquals([$feed, [$item]], $result); $this->assertEquals([$feed, [$item]], $result);
} }
public function testNoFavicon() public function testNoFavicon()
{ {
$this->_setUpReader($this->_url); $this->__setUpReader($this->url);
$feed = $this->_createFeed(false); $feed = $this->_createFeed(false);
$this->_favicon->expects($this->never()) $this->favicon->expects($this->never())
->method('get'); ->method('get');
$item = $this->_createItem(); $item = $this->_createItem();
$this->_mockIterator($this->_feed_mock, [$this->_item_mock]); $this->_mockIterator($this->feed_mock, [$this->item_mock]);
$result = $this->_fetcher->fetch($this->_url, false, null, null, null); $result = $this->fetcher->fetch($this->url, false, null, null, null);
$this->assertEquals([$feed, [$item]], $result); $this->assertEquals([$feed, [$item]], $result);
} }
public function testRtl() public function testRtl()
{ {
$this->_setUpReader($this->_url); $this->__setUpReader($this->url);
$this->_createFeed('he-IL'); $this->_createFeed('he-IL');
$this->_createItem(); $this->_createItem();
$this->_mockIterator($this->_feed_mock, [$this->_item_mock]); $this->_mockIterator($this->feed_mock, [$this->item_mock]);
list($feed, $items) = $this->_fetcher->fetch($this->_url, false, null, null, null); list($feed, $items) = $this->fetcher->fetch($this->url, false, null, null, null);
$this->assertTrue($items[0]->getRtl()); $this->assertTrue($items[0]->getRtl());
} }
public function testRssPubDate() public function testRssPubDate()
{ {
$this->_setUpReader($this->_url); $this->__setUpReader($this->url);
$this->_createFeed('he-IL'); $this->_createFeed('he-IL');
$this->_createItem(); $this->_createItem();
$this->_item_mock->expects($this->exactly(2)) $this->item_mock->expects($this->exactly(2))
->method('getValue') ->method('getValue')
->will($this->returnValueMap([ ->will($this->returnValueMap([
['pubDate', '2018-03-27T19:50:29Z'], ['pubDate', '2018-03-27T19:50:29Z'],
@ -265,18 +310,18 @@ class FeedFetcherTest extends TestCase
])); ]));
$this->_mockIterator($this->_feed_mock, [$this->_item_mock]); $this->_mockIterator($this->feed_mock, [$this->item_mock]);
list($feed, $items) = $this->_fetcher->fetch($this->_url, false, null, null, null); list($feed, $items) = $this->fetcher->fetch($this->url, false, null, null, null);
$this->assertSame($items[0]->getPubDate(), 1522180229); $this->assertSame($items[0]->getPubDate(), 1522180229);
} }
public function testAtomPubDate() public function testAtomPubDate()
{ {
$this->_setUpReader($this->_url); $this->__setUpReader($this->url);
$this->_createFeed('he-IL'); $this->_createFeed('he-IL');
$this->_createItem(); $this->_createItem();
$this->_item_mock->expects($this->exactly(3)) $this->item_mock->expects($this->exactly(3))
->method('getValue') ->method('getValue')
->will($this->returnValueMap([ ->will($this->returnValueMap([
['pubDate', NULL], ['pubDate', NULL],
@ -284,8 +329,8 @@ class FeedFetcherTest extends TestCase
])); ]));
$this->_mockIterator($this->_feed_mock, [$this->_item_mock]); $this->_mockIterator($this->feed_mock, [$this->item_mock]);
list($feed, $items) = $this->_fetcher->fetch($this->_url, false, null, null, null); list($feed, $items) = $this->fetcher->fetch($this->url, false, null, null, null);
$this->assertSame($items[0]->getPubDate(), 1519761029); $this->assertSame($items[0]->getPubDate(), 1519761029);
} }
@ -366,44 +411,44 @@ class FeedFetcherTest extends TestCase
return $iteratorMock; return $iteratorMock;
} }
private function _setUpReader($url='', $modified=true) private function __setUpReader($url = '', $modified = true)
{ {
$this->_reader->expects($this->once()) $this->reader->expects($this->once())
->method('readSince') ->method('read')
->with($this->equalTo($url)) ->with($this->equalTo($url))
->will($this->returnValue($this->_result)); ->will($this->returnValue($this->result));
$this->_result->expects($this->once()) $this->result->expects($this->once())
->method('getResponse') ->method('getResponse')
->will($this->returnValue($this->_response)); ->will($this->returnValue($this->response));
$this->_response->expects($this->once()) $this->response->expects($this->once())
->method('isModified') ->method('isModified')
->will($this->returnValue($modified)); ->will($this->returnValue($modified));
$this->_location = $url; $this->location = $url;
if (!$modified) { if (!$modified) {
$this->_result->expects($this->never()) $this->result->expects($this->never())
->method('getUrl'); ->method('getUrl');
} else { } else {
$this->_result->expects($this->once()) $this->result->expects($this->once())
->method('getUrl') ->method('getUrl')
->will($this->returnValue($this->_location)); ->will($this->returnValue($this->location));
$this->_result->expects($this->once()) $this->result->expects($this->once())
->method('getFeed') ->method('getFeed')
->will($this->returnValue($this->_feed_mock)); ->will($this->returnValue($this->feed_mock));
} }
} }
private function _expectFeed($method, $return, $count = 1) private function _expectFeed($method, $return, $count = 1)
{ {
$this->_feed_mock->expects($this->exactly($count)) $this->feed_mock->expects($this->exactly($count))
->method($method) ->method($method)
->will($this->returnValue($return)); ->will($this->returnValue($return));
} }
private function _expectItem($method, $return, $count = 1) private function _expectItem($method, $return, $count = 1)
{ {
$this->_item_mock->expects($this->exactly($count)) $this->item_mock->expects($this->exactly($count))
->method($method) ->method($method)
->will($this->returnValue($return)); ->will($this->returnValue($return));
} }
@ -411,26 +456,26 @@ class FeedFetcherTest extends TestCase
private function _createItem($enclosureType=null) private function _createItem($enclosureType=null)
{ {
$this->_expectItem('getLink', $this->_permalink); $this->_expectItem('getLink', $this->permalink);
$this->_expectItem('getTitle', $this->_title); $this->_expectItem('getTitle', $this->title);
$this->_expectItem('getPublicId', $this->_guid); $this->_expectItem('getPublicId', $this->guid);
$this->_expectItem('getDescription', $this->_body); $this->_expectItem('getDescription', $this->body);
$this->_expectItem('getLastModified', $this->_modified, 2); $this->_expectItem('getLastModified', $this->modified);
$this->_expectItem('getAuthor', $this->_author); $this->_expectItem('getAuthor', $this->author);
$item = new Item(); $item = new Item();
$item->setStatus(0); $item->setStatus(0);
$item->setUnread(true); $item->setUnread(true);
$item->setUrl($this->_permalink); $item->setUrl($this->permalink);
$item->setTitle('my<\' title'); $item->setTitle('my<\' title');
$item->setGuid($this->_guid); $item->setGuid($this->guid);
$item->setGuidHash($this->_guid); $item->setGuidHash($this->guid_hash);
$item->setBody($this->_body); $item->setBody($this->body);
$item->setRtl(false); $item->setRtl(false);
$item->setLastModified(3); $item->setLastModified(3);
$item->setPubDate(3); $item->setPubDate(3);
$item->setAuthor(html_entity_decode($this->_author)); $item->setAuthor(html_entity_decode($this->author->getName()));
if ($enclosureType === 'audio/ogg' || $enclosureType === 'video/ogg') { if ($enclosureType === 'audio/ogg' || $enclosureType === 'video/ogg') {
$media = $this->getMockbuilder(MediaInterface::class)->getMock(); $media = $this->getMockbuilder(MediaInterface::class)->getMock();
@ -443,12 +488,12 @@ class FeedFetcherTest extends TestCase
->will($this->returnValue($enclosureType)); ->will($this->returnValue($enclosureType));
$media2->expects($this->once()) $media2->expects($this->once())
->method('getUrl') ->method('getUrl')
->will($this->returnValue($this->_enclosure)); ->will($this->returnValue($this->enclosure));
$this->_expectItem('hasMedia', true); $this->_expectItem('hasMedia', true);
$this->_expectItem('getMedias', [$media, $media2]); $this->_expectItem('getMedias', [$media, $media2]);
$item->setEnclosureMime($enclosureType); $item->setEnclosureMime($enclosureType);
$item->setEnclosureLink($this->_enclosure); $item->setEnclosureLink($this->enclosure);
} }
$item->generateSearchIndex(); $item->generateSearchIndex();
@ -458,27 +503,27 @@ class FeedFetcherTest extends TestCase
private function _createFeed($lang='de-DE', $favicon=false) private function _createFeed($lang='de-DE', $favicon=false)
{ {
$this->_expectFeed('getTitle', $this->_feed_title); $this->_expectFeed('getTitle', $this->feed_title, 2);
$this->_expectFeed('getLink', $this->_feed_link); $this->_expectFeed('getLink', $this->feed_link);
$this->_expectFeed('getLastModified', $this->_modified); $this->_expectFeed('getLastModified', $this->modified);
$this->_expectFeed('getLanguage', $lang); $this->_expectFeed('getLanguage', $lang);
$feed = new Feed(); $feed = new Feed();
$feed->setTitle('&its a title'); $feed->setTitle('&its a title');
$feed->setLink($this->_feed_link); $feed->setLink($this->feed_link);
$feed->setLocation($this->_location); $feed->setLocation($this->location);
$feed->setUrl($this->_url); $feed->setUrl($this->url);
$feed->setLastModified(3); $feed->setLastModified(3);
$feed->setAdded($this->_time); $feed->setAdded($this->time);
if ($favicon) { if ($favicon) {
$feed->setFaviconLink('http://anon.google.com'); $feed->setFaviconLink('http://anon.google.com');
$this->_favicon->expects($this->exactly(1)) $this->favicon->expects($this->exactly(1))
->method('get') ->method('get')
->with($this->equalTo($this->_feed_link)) ->with($this->equalTo($this->feed_link))
->will($this->returnValue($this->_web_favicon)); ->will($this->returnValue($this->web_favicon));
} else { } else {
$this->_favicon->expects($this->never()) $this->favicon->expects($this->never())
->method('get'); ->method('get');
} }