From 9b1fe46fe995bc103d3c5cfa9a552d050ff0ead8 Mon Sep 17 00:00:00 2001 From: Bernhard Posselt Date: Sat, 23 Jul 2016 18:34:17 +0200 Subject: Add timestamps for all entities in milisecond unix time format --- appinfo/database.xml | 8 ++++++++ appinfo/info.xml | 2 +- db/feed.php | 2 ++ db/feedmapper.php | 5 +++-- db/foldermapper.php | 5 +++-- db/itemmapper.php | 6 +++--- db/mapperfactory.php | 14 ++++++++++---- db/mysql/itemmapper.php | 5 +++-- db/newsmapper.php | 31 ++++++++++++++++++++++++++----- fetcher/feedfetcher.php | 5 ++--- service/feedservice.php | 5 ++--- service/folderservice.php | 12 ++++++------ service/itemservice.php | 13 ++++++------- tests/unit/db/FeedMapperTest.php | 4 +++- tests/unit/db/FolderMapperTest.php | 4 +++- tests/unit/db/ItemMapperTest.php | 4 +++- tests/unit/db/MapperFactoryTest.php | 7 ++++--- tests/unit/db/mysql/ItemMapperTest.php | 4 ++-- tests/unit/fetcher/FeedFetcherTest.php | 3 +-- tests/unit/service/FeedServiceTest.php | 4 +--- tests/unit/service/FolderServiceTest.php | 2 +- tests/unit/service/ItemServiceTest.php | 7 ++++--- utility/time.php | 30 ++++++++++++++++++++++++++++++ 23 files changed, 127 insertions(+), 55 deletions(-) create mode 100644 utility/time.php diff --git a/appinfo/database.xml b/appinfo/database.xml index d12df002e..8756a8ff5 100644 --- a/appinfo/database.xml +++ b/appinfo/database.xml @@ -92,6 +92,14 @@ true 64 + + last_modified + integer + + 8 + false + true + url_hash text diff --git a/appinfo/info.xml b/appinfo/info.xml index dc8cad72e..389861bec 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -3,7 +3,7 @@ news News An RSS/Atom feed reader - 8.8.3 + 8.8.4 agpl Bernhard Posselt Alessandro Cosentino diff --git a/db/feed.php b/db/feed.php index 3a8444276..62d49c01b 100644 --- a/db/feed.php +++ b/db/feed.php @@ -80,6 +80,7 @@ class Feed extends Entity implements IAPI, \JsonSerializable { protected $deletedAt; protected $articlesPerUpdate; protected $httpLastModified; + protected $lastModified; protected $httpEtag; protected $location; protected $ordering; @@ -104,6 +105,7 @@ class Feed extends Entity implements IAPI, \JsonSerializable { $this->addType('fullTextEnabled', 'boolean'); $this->addType('updateMode', 'integer'); $this->addType('updateErrorCount', 'integer'); + $this->addType('lastModified', 'integer'); } diff --git a/db/feedmapper.php b/db/feedmapper.php index 93d919410..80d75e723 100644 --- a/db/feedmapper.php +++ b/db/feedmapper.php @@ -13,6 +13,7 @@ namespace OCA\News\Db; +use OCA\News\Utility\Time; use OCP\IDBConnection; use OCP\AppFramework\Db\Entity; @@ -20,8 +21,8 @@ use OCP\AppFramework\Db\Entity; class FeedMapper extends NewsMapper { - public function __construct(IDBConnection $db) { - parent::__construct($db, 'news_feeds', Feed::class); + public function __construct(IDBConnection $db, Time $time) { + parent::__construct($db, 'news_feeds', Feed::class, $time); } diff --git a/db/foldermapper.php b/db/foldermapper.php index 498b1b6f8..30acb455c 100644 --- a/db/foldermapper.php +++ b/db/foldermapper.php @@ -13,13 +13,14 @@ namespace OCA\News\Db; +use OCA\News\Utility\Time; use OCP\IDBConnection; use OCP\AppFramework\Db\Entity; class FolderMapper extends NewsMapper { - public function __construct(IDBConnection $db) { - parent::__construct($db, 'news_folders', Folder::class); + public function __construct(IDBConnection $db, Time $time) { + parent::__construct($db, 'news_folders', Folder::class, $time); } public function find($id, $userId){ diff --git a/db/itemmapper.php b/db/itemmapper.php index 220b4f153..091022c6c 100644 --- a/db/itemmapper.php +++ b/db/itemmapper.php @@ -14,16 +14,16 @@ namespace OCA\News\Db; use Exception; +use OCA\News\Utility\Time; use OCP\IDBConnection; class ItemMapper extends NewsMapper { - public function __construct(IDBConnection $db) { - parent::__construct($db, 'news_items', Item::class); + public function __construct(IDBConnection $db, Time $time) { + parent::__construct($db, 'news_items', Item::class, $time); } - private function makeSelectQuery($prependTo = '', $oldestFirst = false, $distinctFingerprint = false) { if ($oldestFirst) { diff --git a/db/mapperfactory.php b/db/mapperfactory.php index adcde6c4a..9e99e44bc 100644 --- a/db/mapperfactory.php +++ b/db/mapperfactory.php @@ -13,6 +13,7 @@ namespace OCA\News\Db; +use OCA\News\Utility\Time; use OCP\IDBConnection; use OCA\News\Db\Mysql\ItemMapper as MysqlItemMapper; @@ -23,18 +24,23 @@ class MapperFactory implements IFactory { private $dbType; private $db; + /** + * @var Time + */ + private $time; - public function __construct(IDBConnection $db, $databaseType) { + public function __construct(IDBConnection $db, $databaseType, Time $time) { $this->dbType = $databaseType; $this->db = $db; - } + $this->time = $time; + } public function build() { switch($this->dbType) { case 'mysql': - return new MysqlItemMapper($this->db); + return new MysqlItemMapper($this->db, $this->time); default: - return new ItemMapper($this->db); + return new ItemMapper($this->db, $this->time); } } diff --git a/db/mysql/itemmapper.php b/db/mysql/itemmapper.php index 633f13967..70eefe457 100644 --- a/db/mysql/itemmapper.php +++ b/db/mysql/itemmapper.php @@ -13,6 +13,7 @@ namespace OCA\News\Db\Mysql; +use OCA\News\Utility\Time; use OCP\IDBConnection; use OCA\News\Db\StatusFlag; @@ -20,8 +21,8 @@ use OCA\News\Db\StatusFlag; class ItemMapper extends \OCA\News\Db\ItemMapper { - public function __construct(IDBConnection $db){ - parent::__construct($db); + public function __construct(IDBConnection $db, Time $time){ + parent::__construct($db, $time); } diff --git a/db/newsmapper.php b/db/newsmapper.php index feef949e8..0acc252b9 100644 --- a/db/newsmapper.php +++ b/db/newsmapper.php @@ -5,26 +5,46 @@ * This file is licensed under the Affero General Public License version 3 or * later. See the COPYING file. * - * @author Alessandro Cosentino - * @author Bernhard Posselt + * @author Alessandro Cosentino + * @author Bernhard Posselt * @copyright Alessandro Cosentino 2012 * @copyright Bernhard Posselt 2012, 2014 */ namespace OCA\News\Db; +use OCA\News\Utility\Time; use OCP\IDBConnection; use OCP\AppFramework\Db\Mapper; +use OCP\AppFramework\Db\Entity; abstract class NewsMapper extends Mapper { - public function __construct(IDBConnection $db, $table, $entity) { + /** + * @var Time + */ + private $time; + + public function __construct(IDBConnection $db, $table, $entity, + Time $time) { parent::__construct($db, $table, $entity); + $this->time = $time; + } + + public function update(Entity $entity) { + $entity->setLastModified($this->time->getMicroTime()); + return parent::update($entity); + } + + public function insert(Entity $entity) { + $entity->setLastModified($this->time->getMicroTime()); + return parent::insert($entity); } /** - * @param int $id the id of the feed + * @param int $id the id of the feed * @param string $userId the id of the user + * * @return \OCP\AppFramework\Db\Entity */ abstract public function find($id, $userId); @@ -38,10 +58,11 @@ abstract class NewsMapper extends Mapper { * * @param array $search an assoc array from property to filter value * @param int $limit + * * @paran int $offset * @return array */ - public function where(array $search=[], $limit=null, $offset=null) { + public function where(array $search = [], $limit = null, $offset = null) { $entity = new $this->entityClass; // turn keys into sql query filter, e.g. feedId -> feed_id = :feedId diff --git a/fetcher/feedfetcher.php b/fetcher/feedfetcher.php index a85a17c71..beffe9051 100644 --- a/fetcher/feedfetcher.php +++ b/fetcher/feedfetcher.php @@ -29,12 +29,12 @@ use PicoFeed\Client\ForbiddenException; use PicoFeed\Client\UnauthorizedException; use OCP\IL10N; -use OCP\AppFramework\Utility\ITimeFactory; use OCA\News\Db\Item; use OCA\News\Db\Feed; use OCA\News\Utility\PicoFeedFaviconFactory; use OCA\News\Utility\PicoFeedReaderFactory; +use OCA\News\Utility\Time; class FeedFetcher implements IFeedFetcher { @@ -46,7 +46,7 @@ class FeedFetcher implements IFeedFetcher { public function __construct(Reader $reader, PicoFeedFaviconFactory $faviconFactory, IL10N $l10n, - ITimeFactory $time) { + Time $time) { $this->faviconFactory = $faviconFactory; $this->reader = $reader; $this->time = $time; @@ -241,7 +241,6 @@ class FeedFetcher implements IFeedFetcher { $item->setGuid($parsedItem->getId()); $item->setGuidHash($item->getGuid()); $item->setPubDate($parsedItem->getDate()->getTimestamp()); - $item->setLastModified($this->time->getTime()); $item->setRtl($this->determineRtl($parsedItem, $parsedFeed)); // unescape content because angularjs helps against XSS diff --git a/service/feedservice.php b/service/feedservice.php index 88087a874..2d9bc6728 100644 --- a/service/feedservice.php +++ b/service/feedservice.php @@ -18,7 +18,6 @@ use HTMLPurifier; use OCP\ILogger; use OCP\IL10N; use OCP\AppFramework\Db\DoesNotExistException; -use OCP\AppFramework\Utility\ITimeFactory; use OCA\News\Db\Feed; use OCA\News\Db\Item; @@ -27,6 +26,7 @@ use OCA\News\Db\ItemMapper; use OCA\News\Fetcher\Fetcher; use OCA\News\Fetcher\FetcherException; use OCA\News\Config\Config; +use OCA\News\Utility\Time; class FeedService extends Service { @@ -46,7 +46,7 @@ class FeedService extends Service { ItemMapper $itemMapper, ILogger $logger, IL10N $l10n, - ITimeFactory $timeFactory, + Time $timeFactory, Config $config, HTMLPurifier $purifier, $LoggerParameters){ @@ -315,7 +315,6 @@ class FeedService extends Service { // if the feed does not exist, create a separate feed for them foreach ($json as $entry) { $item = Item::fromImport($entry); - $item->setLastModified($this->timeFactory->getTime()); $feedLink = $entry['feedLink']; // this is not set on the item yet if(array_key_exists($feedLink, $feedsDict)) { diff --git a/service/folderservice.php b/service/folderservice.php index 0212c682c..e7daf836e 100644 --- a/service/folderservice.php +++ b/service/folderservice.php @@ -13,11 +13,11 @@ namespace OCA\News\Service; -use \OCP\IL10N; -use \OCP\AppFramework\Utility\ITimeFactory; -use \OCA\News\Db\Folder; -use \OCA\News\Db\FolderMapper; -use \OCA\News\Config\Config; +use OCP\IL10N; +use OCA\News\Db\Folder; +use OCA\News\Db\FolderMapper; +use OCA\News\Config\Config; +use OCA\News\Utility\Time; class FolderService extends Service { @@ -29,7 +29,7 @@ class FolderService extends Service { public function __construct(FolderMapper $folderMapper, IL10N $l10n, - ITimeFactory $timeFactory, + Time $timeFactory, Config $config){ parent::__construct($folderMapper); $this->l10n = $l10n; diff --git a/service/itemservice.php b/service/itemservice.php index a571c15ac..8bbb54d49 100644 --- a/service/itemservice.php +++ b/service/itemservice.php @@ -15,12 +15,12 @@ namespace OCA\News\Service; use OCP\IConfig; use OCP\AppFramework\Db\DoesNotExistException; -use OCP\AppFramework\Utility\ITimeFactory; use OCA\News\Db\ItemMapper; use OCA\News\Db\StatusFlag; use OCA\News\Db\FeedType; use OCA\News\Config\Config; +use OCA\News\Utility\Time; class ItemService extends Service { @@ -33,7 +33,7 @@ class ItemService extends Service { public function __construct(ItemMapper $itemMapper, StatusFlag $statusFlag, - ITimeFactory $timeFactory, + Time $timeFactory, Config $config, IConfig $systemConfig){ parent::__construct($itemMapper); @@ -126,7 +126,6 @@ class ItemService extends Service { $guidHash, $feedId, $userId ); - $item->setLastModified($this->timeFactory->getTime()); if($isStarred){ $item->setStarred(); } else { @@ -148,7 +147,7 @@ class ItemService extends Service { * @throws ServiceNotFoundException if the item does not exist */ public function read($itemId, $isRead, $userId){ - $lastModified = $this->timeFactory->getTime(); + $lastModified = $this->timeFactory->getMicroTime(); $this->itemMapper->readItem($itemId, $isRead, $lastModified, $userId); } @@ -160,7 +159,7 @@ class ItemService extends Service { * @param string $userId the name of the user */ public function readAll($highestItemId, $userId){ - $time = $this->timeFactory->getTime(); + $time = $this->timeFactory->getMicroTime(); $this->itemMapper->readAll($highestItemId, $time, $userId); } @@ -173,7 +172,7 @@ class ItemService extends Service { * @param string $userId the name of the user */ public function readFolder($folderId, $highestItemId, $userId){ - $time = $this->timeFactory->getTime(); + $time = $this->timeFactory->getMicroTime(); $this->itemMapper->readFolder( $folderId, $highestItemId, $time, $userId ); @@ -188,7 +187,7 @@ class ItemService extends Service { * @param string $userId the name of the user */ public function readFeed($feedId, $highestItemId, $userId){ - $time = $this->timeFactory->getTime(); + $time = $this->timeFactory->getMicroTime(); $this->itemMapper->readFeed($feedId, $highestItemId, $time, $userId); } diff --git a/tests/unit/db/FeedMapperTest.php b/tests/unit/db/FeedMapperTest.php index 97488fb88..7e2f8d777 100644 --- a/tests/unit/db/FeedMapperTest.php +++ b/tests/unit/db/FeedMapperTest.php @@ -14,6 +14,8 @@ namespace OCA\News\Db; +use OCA\News\Utility\Time; + class FeedMapperTest extends \OCA\News\Tests\Unit\Db\MapperTestUtility { private $mapper; @@ -22,7 +24,7 @@ class FeedMapperTest extends \OCA\News\Tests\Unit\Db\MapperTestUtility { protected function setUp(){ parent::setUp(); - $this->mapper = new FeedMapper($this->db); + $this->mapper = new FeedMapper($this->db, new Time()); // create mock feeds $feed1 = new Feed(); diff --git a/tests/unit/db/FolderMapperTest.php b/tests/unit/db/FolderMapperTest.php index 00ad2127d..fcb82e7e1 100644 --- a/tests/unit/db/FolderMapperTest.php +++ b/tests/unit/db/FolderMapperTest.php @@ -14,6 +14,8 @@ namespace OCA\News\Db; +use OCA\News\Utility\Time; + class FolderMapperTest extends \OCA\News\Tests\Unit\Db\MapperTestUtility { private $folderMapper; @@ -23,7 +25,7 @@ class FolderMapperTest extends \OCA\News\Tests\Unit\Db\MapperTestUtility { protected function setUp(){ parent::setUp(); - $this->folderMapper = new FolderMapper($this->db); + $this->folderMapper = new FolderMapper($this->db, new Time()); // create mock folders $folder1 = new Folder(); diff --git a/tests/unit/db/ItemMapperTest.php b/tests/unit/db/ItemMapperTest.php index 8b42aebb8..7b11b7862 100644 --- a/tests/unit/db/ItemMapperTest.php +++ b/tests/unit/db/ItemMapperTest.php @@ -14,6 +14,8 @@ namespace OCA\News\Db; +use OCA\News\Utility\Time; + class ItemMapperTest extends \OCA\News\Tests\Unit\Db\MapperTestUtility { private $mapper; @@ -29,7 +31,7 @@ class ItemMapperTest extends \OCA\News\Tests\Unit\Db\MapperTestUtility { public function setUp() { parent::setup(); - $this->mapper = new ItemMapper($this->db); + $this->mapper = new ItemMapper($this->db, new Time()); // create mock items $item1 = new Item(); diff --git a/tests/unit/db/MapperFactoryTest.php b/tests/unit/db/MapperFactoryTest.php index 341dea0e9..1544ddf2c 100644 --- a/tests/unit/db/MapperFactoryTest.php +++ b/tests/unit/db/MapperFactoryTest.php @@ -13,6 +13,7 @@ namespace OCA\News\Db; +use OCA\News\Utility\Time; use PHPUnit_Framework_TestCase; use OCP\IDb; @@ -32,17 +33,17 @@ class MapperFactoryTest extends PHPUnit_Framework_TestCase { } public function testGetItemMapperSqlite() { - $factory = new MapperFactory($this->db, 'sqlite'); + $factory = new MapperFactory($this->db, 'sqlite', new Time()); $this->assertTrue($factory->build() instanceof ItemMapper); } public function testGetItemMapperPostgres() { - $factory = new MapperFactory($this->db, 'pgsql'); + $factory = new MapperFactory($this->db, 'pgsql', new Time()); $this->assertTrue($factory->build() instanceof ItemMapper); } public function testGetItemMapperMysql() { - $factory = new MapperFactory($this->db, 'mysql'); + $factory = new MapperFactory($this->db, 'mysql', new Time()); $this->assertTrue($factory->build() instanceof MysqlMapper); } diff --git a/tests/unit/db/mysql/ItemMapperTest.php b/tests/unit/db/mysql/ItemMapperTest.php index 3c091341a..57f3cd77f 100644 --- a/tests/unit/db/mysql/ItemMapperTest.php +++ b/tests/unit/db/mysql/ItemMapperTest.php @@ -15,7 +15,7 @@ namespace OCA\News\Db\Mysql; use \OCA\News\Db\Item; use \OCA\News\Db\StatusFlag; - +use OCA\News\Utility\Time; class ItemMapperTest extends \OCA\News\Tests\Unit\Db\MapperTestUtility { @@ -32,7 +32,7 @@ class ItemMapperTest extends \OCA\News\Tests\Unit\Db\MapperTestUtility { public function setUp() { parent::setUp(); - $this->mapper = new ItemMapper($this->db); + $this->mapper = new ItemMapper($this->db, new Time()); // create mock items $item1 = new Item(); diff --git a/tests/unit/fetcher/FeedFetcherTest.php b/tests/unit/fetcher/FeedFetcherTest.php index 33383910e..4b91e15c3 100644 --- a/tests/unit/fetcher/FeedFetcherTest.php +++ b/tests/unit/fetcher/FeedFetcherTest.php @@ -90,7 +90,7 @@ class FeedFetcherTest extends \PHPUnit_Framework_TestCase { $this->time = 2323; $timeFactory = $this->getMockBuilder( - '\OCP\AppFramework\Utility\ITimeFactory') + '\OCA\News\Utility\Time') ->disableOriginalConstructor() ->getMock(); $timeFactory->expects($this->any()) @@ -221,7 +221,6 @@ class FeedFetcherTest extends \PHPUnit_Framework_TestCase { $item->setGuid($this->guid); $item->setGuidHash($this->guid); $item->setBody($this->body); - $item->setLastModified($this->time); $item->setRtl(false); $this->expectItem('getAuthor', $this->author); diff --git a/tests/unit/service/FeedServiceTest.php b/tests/unit/service/FeedServiceTest.php index efd7e5f33..ef16b9e78 100644 --- a/tests/unit/service/FeedServiceTest.php +++ b/tests/unit/service/FeedServiceTest.php @@ -47,7 +47,7 @@ class FeedServiceTest extends \PHPUnit_Framework_TestCase { $this->loggerParams = ['hi']; $this->time = 222; $this->autoPurgeMinimumInterval = 10; - $timeFactory = $this->getMockBuilder('\OCP\AppFramework\Utility\ITimeFactory') + $timeFactory = $this->getMockBuilder('\OCA\News\Utility\Time') ->disableOriginalConstructor() ->getMock(); $timeFactory->expects($this->any()) @@ -760,7 +760,6 @@ class FeedServiceTest extends \PHPUnit_Framework_TestCase { $item->setEnclosureLink('lin'); $item->setUnread(); $item->setUnstarred(); - $item->setLastModified($this->time); $item->generateSearchIndex(); $json = $item->toExport(['feed3' => $feed]); @@ -817,7 +816,6 @@ class FeedServiceTest extends \PHPUnit_Framework_TestCase { $item->setEnclosureLink('lin'); $item->setUnread(); $item->setUnstarred(); - $item->setLastModified($this->time); $item->generateSearchIndex(); $json = $item->toExport(['feed3' => $feed]); diff --git a/tests/unit/service/FolderServiceTest.php b/tests/unit/service/FolderServiceTest.php index 275bc8992..319a896d6 100644 --- a/tests/unit/service/FolderServiceTest.php +++ b/tests/unit/service/FolderServiceTest.php @@ -30,7 +30,7 @@ class FolderServiceTest extends \PHPUnit_Framework_TestCase { ->disableOriginalConstructor() ->getMock(); $this->time = 222; - $timeFactory = $this->getMockBuilder('\OCP\AppFramework\Utility\ITimeFactory') + $timeFactory = $this->getMockBuilder('\OCA\News\Utility\Time') ->disableOriginalConstructor() ->getMock(); $timeFactory->expects($this->any()) diff --git a/tests/unit/service/ItemServiceTest.php b/tests/unit/service/ItemServiceTest.php index e9bf47490..e562757f4 100644 --- a/tests/unit/service/ItemServiceTest.php +++ b/tests/unit/service/ItemServiceTest.php @@ -34,12 +34,15 @@ class ItemServiceTest extends \PHPUnit_Framework_TestCase { protected function setUp(){ $this->time = 222; - $this->timeFactory = $this->getMockBuilder('\OCP\AppFramework\Utility\ITimeFactory') + $this->timeFactory = $this->getMockBuilder('\OCA\News\Utility\Time') ->disableOriginalConstructor() ->getMock(); $this->timeFactory->expects($this->any()) ->method('getTime') ->will($this->returnValue($this->time)); + $this->timeFactory->expects($this->any()) + ->method('getMicroTime') + ->will($this->returnValue($this->time)); $this->mapper = $this->getMockBuilder('\OCA\News\Db\ItemMapper') ->disableOriginalConstructor() ->getMock(); @@ -219,7 +222,6 @@ class ItemServiceTest extends \PHPUnit_Framework_TestCase { $expectedItem->setStatus(128); $expectedItem->setStarred(); $expectedItem->setId($itemId); - $expectedItem->setLastModified($this->time); $this->mapper->expects($this->once()) ->method('findByGuidHash') @@ -253,7 +255,6 @@ class ItemServiceTest extends \PHPUnit_Framework_TestCase { $expectedItem->setStatus(128); $expectedItem->setUnstarred(); $expectedItem->setId($itemId); - $expectedItem->setLastModified($this->time); $this->mapper->expects($this->once()) ->method('findByGuidHash') diff --git a/utility/time.php b/utility/time.php new file mode 100644 index 000000000..e6ea2b470 --- /dev/null +++ b/utility/time.php @@ -0,0 +1,30 @@ + + * @copyright Bernhard Posselt 2016 + */ + +namespace OCA\News\Utility; + +class Time { + public function getTime() { + return time(); + } + + /** + * @return int the current unix time in miliseconds + */ + public function getMicroTime() { + $utimestamp = microtime(true); + $timestamp = floor($utimestamp); + $milliseconds = round(($utimestamp - $timestamp) * 1000000); + $result = ($timestamp * 1000000) + $milliseconds; + return $result; + } + +} \ No newline at end of file -- cgit v1.2.3