diff options
40 files changed, 2382 insertions, 2387 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 6874d02f6..a875cec74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,13 @@ # Changelog All notable changes to this project will be documented in this file. - The format is almost based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), older entries don't fully match. ## [Unreleased] +### Changed +- Remove outdated feed DB code +- add background & hover for entries + ## [15.1.1] - 2020-12-27 ### Changed diff --git a/lib/Command/Updater/UpdateFeed.php b/lib/Command/Updater/UpdateFeed.php index 93fa2a8d3..4ffb8f57a 100644 --- a/lib/Command/Updater/UpdateFeed.php +++ b/lib/Command/Updater/UpdateFeed.php @@ -51,7 +51,7 @@ class UpdateFeed extends Command $feedId = $input->getArgument('feed-id'); $userId = $input->getArgument('user-id'); try { - $feed = $this->feedService->findForUser($userId, $feedId); + $feed = $this->feedService->find($userId, $feedId); $updated_feed = $this->feedService->fetch($feed); } catch (\Exception $e) { $output->writeln( diff --git a/lib/Controller/EntityApiSerializer.php b/lib/Controller/EntityApiSerializer.php deleted file mode 100644 index daa0f20e5..000000000 --- a/lib/Controller/EntityApiSerializer.php +++ /dev/null @@ -1,76 +0,0 @@ -<?php -/** - * Nextcloud - News - * - * This file is licensed under the Affero General Public License version 3 or - * later. See the COPYING file. - * - * @author Bernhard Posselt <dev@bernhard-posselt.com> - * @copyright 2012-2014 Bernhard Posselt - */ - -namespace OCA\News\Controller; - -use \OCA\News\Db\IAPI; - -/** - * Class EntityApiSerializer - * - * @package OCA\News\Controller - * @deprecated use ApiPayloadTrait - */ -class EntityApiSerializer -{ - - private $level; - - public function __construct($level) - { - $this->level = $level; - } - - - /** - * Call toAPI() method on all entities. Works on - * - * @param mixed $data : - * * Entity - * * Entity[] - * * array('level' => Entity[]) - * * Response - * @return array|mixed - */ - public function serialize($data) - { - - if ($data instanceof IAPI) { - return [$this->level => [$data->toAPI()]]; - } - - if (is_array($data) && array_key_exists($this->level, $data)) { - $data[$this->level] = $this->convert($data[$this->level]); - } elseif (is_array($data)) { - $data = [$this->level => $this->convert($data)]; - } - - return $data; - } - - - private function convert(array $entities) - { - $converted = []; - - foreach ($entities as $entity) { - if ($entity instanceof IAPI) { - $converted[] = $entity->toAPI(); - - // break if it contains anything else than entities - } else { - return $entities; - } - } - - return $converted; - } -} diff --git a/lib/Controller/FeedApiController.php b/lib/Controller/FeedApiController.php index eb6edcad2..af552f411 100644 --- a/lib/Controller/FeedApiController.php +++ b/lib/Controller/FeedApiController.php @@ -25,10 +25,8 @@ use \OCP\IRequest; use \OCP\IUserSession; use \OCP\AppFramework\Http; -use \OCA\News\Service\FeedService; use \OCA\News\Service\ItemService; use Psr\Log\LoggerInterface; -use function GuzzleHttp\Psr7\uri_for; class FeedApiController extends ApiController { @@ -46,12 +44,6 @@ class FeedApiController extends ApiController private $feedService; /** - * TODO: Remove - * @var FeedService - */ - private $oldFeedService; - - /** * @var LoggerInterface */ private $logger; @@ -64,14 +56,12 @@ class FeedApiController extends ApiController public function __construct( IRequest $request, ?IUserSession $userSession, - FeedService $oldFeedService, FeedServiceV2 $feedService, ItemService $oldItemService, LoggerInterface $logger ) { parent::__construct($request, $userSession); $this->feedService = $feedService; - $this->oldFeedService = $oldFeedService; $this->oldItemService = $oldItemService; $this->logger = $logger; } @@ -189,11 +179,9 @@ class FeedApiController extends ApiController } try { - $this->oldFeedService->patch( - $feedId, - $this->getUserId(), - ['folderId' => $folderId] - ); + $feed = $this->feedService->find($this->getUserId(), $feedId); + $feed->setFolderId($folderId); + $this->feedService->update($this->getUserId(), $feed); } catch (ServiceNotFoundException $ex) { return $this->error($ex, Http::STATUS_NOT_FOUND); } @@ -215,11 +203,9 @@ class FeedApiController extends ApiController public function rename(int $feedId, string $feedTitle) { try { - $this->oldFeedService->patch( - $feedId, - $this->getUserId(), - ['title' => $feedTitle] - ); + $feed = $this->feedService->find($this->getUserId(), $feedId); + $feed->setTitle($feedTitle); + $this->feedService->update($this->getUserId(), $feed); } catch (ServiceNotFoundException $ex) { return $this->error($ex, Http::STATUS_NOT_FOUND); } diff --git a/lib/Controller/FeedController.php b/lib/Controller/FeedController.php index 5abcd3393..ba39fdf7a 100644 --- a/lib/Controller/FeedController.php +++ b/lib/Controller/FeedController.php @@ -15,14 +15,15 @@ namespace OCA\News\Controller; use OCA\News\Service\Exceptions\ServiceConflictException; use OCA\News\Service\Exceptions\ServiceNotFoundException; +use OCA\News\Service\FeedServiceV2; use OCA\News\Service\FolderServiceV2; +use OCA\News\Service\ImportService; use OCP\AppFramework\Http\JSONResponse; use OCP\IRequest; use OCP\IConfig; use OCP\AppFramework\Http; use OCA\News\Service\ItemService; -use OCA\News\Service\FeedService; use OCA\News\Db\FeedType; use OCP\IUserSession; @@ -30,7 +31,9 @@ class FeedController extends Controller { use JSONHttpErrorTrait; - //TODO: Remove + /** + * @var FeedServiceV2 + */ private $feedService; //TODO: Remove private $itemService; @@ -39,6 +42,10 @@ class FeedController extends Controller */ private $folderService; /** + * @var ImportService + */ + private $importService; + /** * @var IConfig */ private $settings; @@ -46,8 +53,9 @@ class FeedController extends Controller public function __construct( IRequest $request, FolderServiceV2 $folderService, - FeedService $feedService, + FeedServiceV2 $feedService, ItemService $itemService, + ImportService $importService, IConfig $settings, ?IUserSession $userSession ) { @@ -55,6 +63,7 @@ class FeedController extends Controller $this->folderService = $folderService; $this->feedService = $feedService; $this->itemService = $itemService; + $this->importService = $importService; $this->settings = $settings; } @@ -74,12 +83,13 @@ class FeedController extends Controller ]; try { - $params['newestItemId'] = - $this->itemService->getNewestItemId($this->getUserId()); + $id = $this->itemService->getNewestItemId($this->getUserId()); // An exception occurs if there is a newest item. If there is none, // simply ignore it and do not add the newestItemId + $params['newestItemId'] = $id; } catch (ServiceNotFoundException $ex) { + //NO-OP } return $params; @@ -102,24 +112,22 @@ class FeedController extends Controller 'lastViewedFeedType' ); - // cast from null to int is 0 - if ($feedType !== null) { - $feedType = (int) $feedType; - } - // check if feed or folder exists try { - if ($feedType === FeedType::FOLDER) { - if ($feedId === 0) { - $feedId = null; - } - $this->folderService->find($this->getUserId(), $feedId); - } elseif ($feedType === FeedType::FEED) { - $this->feedService->find($this->getUserId(), $feedId); - - // if its the first launch, those values will be null - } elseif ($feedType === null) { - throw new ServiceNotFoundException(''); + if ($feedType === null) { + throw new ServiceNotFoundException('First launch'); + } + + $feedType = intval($feedType); + switch ($feedType) { + case FeedType::FOLDER: + $this->folderService->find($this->getUserId(), $feedId); + break; + case FeedType::FEED: + $this->feedService->find($this->getUserId(), $feedId); + break; + default: + break; } } catch (ServiceNotFoundException $ex) { $feedId = 0; @@ -162,9 +170,10 @@ class FeedController extends Controller $this->feedService->purgeDeleted($this->getUserId(), false); $feed = $this->feedService->create( + $this->getUserId(), $url, $parentFolderId, - $this->getUserId(), + false, $title, $user, $password @@ -172,12 +181,12 @@ class FeedController extends Controller $params = ['feeds' => [$feed]]; try { - $params['newestItemId'] = - $this->itemService->getNewestItemId($this->getUserId()); - + $id = $this->itemService->getNewestItemId($this->getUserId()); // An exception occurs if there is a newest item. If there is none, // simply ignore it and do not add the newestItemId + $params['newestItemId'] = $id; } catch (ServiceNotFoundException $ex) { + //NO-OP } return $params; @@ -199,7 +208,9 @@ class FeedController extends Controller public function delete(int $feedId) { try { - $this->feedService->markDeleted($feedId, $this->getUserId()); + $feed = $this->feedService->find($this->getUserId(), $feedId); + $feed->setDeletedAt(time()); + $this->feedService->update($this->getUserId(), $feed); } catch (ServiceNotFoundException $ex) { return $this->error($ex, Http::STATUS_NOT_FOUND); } @@ -218,7 +229,8 @@ class FeedController extends Controller public function update(int $feedId) { try { - $feed = $this->feedService->update($this->getUserId(), $feedId); + $old_feed = $this->feedService->find($this->getUserId(), $feedId); + $feed = $this->feedService->fetch($old_feed); return [ 'feeds' => [ @@ -244,7 +256,7 @@ class FeedController extends Controller */ public function import(array $json): array { - $feed = $this->feedService->importArticles($json, $this->getUserId()); + $feed = $this->importService->importArticles($this->getUserId(), $json); $params = [ 'starred' => $this->itemService->starredCount($this->getUserId()) @@ -290,7 +302,9 @@ class FeedController extends Controller public function restore(int $feedId) { try { - $this->feedService->unmarkDeleted($feedId, $this->getUserId()); + $feed = $this->feedService->find($this->getUserId(), $feedId); + $feed->setDeletedAt(null); + $this->feedService->update($this->getUserId(), $feed); } catch (ServiceNotFoundException $ex) { return $this->error($ex, Http::STATUS_NOT_FOUND); } @@ -320,24 +334,32 @@ class FeedController extends Controller ?int $folderId = null, ?string $title = null ) { - $attributes = [ - 'pinned' => $pinned, - 'fullTextEnabled' => $fullTextEnabled, - 'updateMode' => $updateMode, - 'ordering' => $ordering, - 'title' => $title, - 'folderId' => $folderId === 0 ? null : $folderId - ]; + try { + $feed = $this->feedService->find($this->getUserId(), $feedId); + } catch (ServiceNotFoundException $ex) { + return $this->error($ex, Http::STATUS_NOT_FOUND); + } - $diff = array_filter( - $attributes, - function ($value) { - return $value !== null; - } - ); + $fId = $folderId === 0 ? null : $folderId; + $feed->setFolderId($fId); + if ($pinned !== null) { + $feed->setPinned($pinned); + } + if ($fullTextEnabled !== null) { + $feed->setFullTextEnabled($fullTextEnabled); + } + if ($updateMode !== null) { + $feed->setUpdateMode($updateMode); + } + if ($ordering !== null) { + $feed->setOrdering($ordering); + } + if ($title !== null) { + $feed->setTitle($title); + } try { - $this->feedService->patch($feedId, $this->getUserId(), $diff); + $this->feedService->update($this->getUserId(), $feed); } catch (ServiceNotFoundException $ex) { return $this->error($ex, Http::STATUS_NOT_FOUND); } diff --git a/lib/Controller/FolderController.php b/lib/Controller/FolderController.php index b33f46c54..acf3f0109 100644 --- a/lib/Controller/FolderController.php +++ b/lib/Controller/FolderController.php @@ -14,12 +14,12 @@ namespace OCA\News\Controller; use OCA\News\Service\Exceptions\ServiceException; +use OCA\News\Service\FeedServiceV2; use OCP\AppFramework\Http\JSONResponse; use \OCP\IRequest; use \OCP\AppFramework\Http; use \OCA\News\Service\FolderServiceV2; -use \OCA\News\Service\FeedService; use \OCA\News\Service\ItemService; use \OCA\News\Service\Exceptions\ServiceNotFoundException; use \OCA\News\Service\Exceptions\ServiceConflictException; @@ -33,7 +33,9 @@ class FolderController extends Controller * @var FolderServiceV2 */ private $folderService; - //TODO: Remove + /** + * @var FeedServiceV2 + */ private $feedService; //TODO: Remove private $itemService; @@ -41,7 +43,7 @@ class FolderController extends Controller public function __construct( IRequest $request, FolderServiceV2 $folderService, - FeedService $feedService, + FeedServiceV2 $feedService, ItemService $itemService, ?IUserSession $userSession ) { diff --git a/lib/Controller/ItemController.php b/lib/Controller/ItemController.php index 7506891d4..8783a5286 100644 --- a/lib/Controller/ItemController.php +++ b/lib/Controller/ItemController.php @@ -13,6 +13,7 @@ namespace OCA\News\Controller; +use OCA\News\Service\FeedServiceV2; use \OCP\IRequest; use \OCP\IConfig; use \OCP\AppFramework\Http; @@ -20,7 +21,6 @@ use \OCP\AppFramework\Http; use \OCA\News\Service\Exceptions\ServiceException; use \OCA\News\Service\Exceptions\ServiceNotFoundException; use \OCA\News\Service\ItemService; -use \OCA\News\Service\FeedService; use OCP\IUserSession; class ItemController extends Controller @@ -28,12 +28,18 @@ class ItemController extends Controller use JSONHttpErrorTrait; private $itemService; + /** + * @var FeedServiceV2 + */ private $feedService; + /** + * @var IConfig + */ private $settings; public function __construct( IRequest $request, - FeedService $feedService, + FeedServiceV2 $feedService, ItemService $itemService, IConfig $settings, ?IUserSession $userSession diff --git a/lib/Db/Feed.php b/lib/Db/Feed.php index 473912acc..1d5721d3b 100644 --- a/lib/Db/Feed.php +++ b/lib/Db/Feed.php @@ -25,6 +25,16 @@ class Feed extends Entity implements IAPI, \JsonSerializable { use EntityJSONSerializer; + /** + * Silently import new items + */ + const UPDATE_MODE_SILENT = 0; + + /** + * Mark new items as unread. + */ + const UPDATE_MODE_NORMAL = 1; + /** @var string */ protected $userId = ''; /** @var string */ diff --git a/lib/Db/FeedMapper.php b/lib/Db/FeedMapper.php deleted file mode 100644 index cf12c4dfa..000000000 --- a/lib/Db/FeedMapper.php +++ /dev/null @@ -1,202 +0,0 @@ -<?php -/** - * Nextcloud - News - * - * This file is licensed under the Affero General Public License version 3 or - * later. See the COPYING file. - * - * @author Alessandro Cosentino <cosenal@gmail.com> - * @author Bernhard Posselt <dev@bernhard-posselt.com> - * @copyright 2012 Alessandro Cosentino - * @copyright 2012-2014 Bernhard Posselt - */ - -namespace OCA\News\Db; - -use OCA\News\Utility\Time; -use OCP\AppFramework\Db\DoesNotExistException; -use OCP\AppFramework\Db\MultipleObjectsReturnedException; -use OCP\IDBConnection; -use OCP\AppFramework\Db\Entity; - -/** - * Class LegacyFeedMapper - * - * @package OCA\News\Db - * @deprecated use FeedMapper - */ -class FeedMapper extends NewsMapper -{ - const TABLE_NAME = 'news_feeds'; - - public function __construct(IDBConnection $db, Time $time) - { - parent::__construct($db, $time, Feed::class); - } - - - public function find(string $userId, int $id) - { - $sql = 'SELECT `feeds`.*, `item_numbers`.`unread_count` ' . - 'FROM `*PREFIX*news_feeds` `feeds` ' . - 'JOIN ( ' . - 'SELECT `feeds`.`id`, COUNT(`items`.`id`) AS `unread_count` ' . - 'FROM `*PREFIX*news_feeds` `feeds` ' . - 'LEFT JOIN `*PREFIX*news_items` `items` ' . - 'ON `feeds`.`id` = `items`.`feed_id` ' . - // WARNING: this is a desperate attempt at making this query - // work because prepared statements dont work. This is a - // POSSIBLE SQL INJECTION RISK WHEN MODIFIED WITHOUT THOUGHT. - // think twice when changing this - 'AND `items`.`unread` = ? ' . - 'WHERE `feeds`.`id` = ? ' . - 'AND `feeds`.`user_id` = ? ' . - 'GROUP BY `feeds`.`id` ' . - ') `item_numbers` ' . - 'ON `item_numbers`.`id` = `feeds`.`id` '; - $params = [true, $id, $userId]; - - return $this->findEntity($sql, $params); - } - - - public function findAllFromUser(string $userId): array - { - $sql = 'SELECT `feeds`.*, `item_numbers`.`unread_count` ' . - 'FROM `*PREFIX*news_feeds` `feeds` ' . - 'JOIN ( ' . - 'SELECT `feeds`.`id`, COUNT(`items`.`id`) AS `unread_count` ' . - 'FROM `*PREFIX*news_feeds` `feeds` ' . - 'LEFT OUTER JOIN `*PREFIX*news_folders` `folders` ' . - 'ON `feeds`.`folder_id` = `folders`.`id` ' . - 'LEFT JOIN `*PREFIX*news_items` `items` ' . - 'ON `feeds`.`id` = `items`.`feed_id` ' . - // WARNING: this is a desperate attempt at making this query - // work because prepared statements dont work. This is a - // POSSIBLE SQL INJECTION RISK WHEN MODIFIED WITHOUT THOUGHT. - // think twice when changing this - 'AND `items`.`unread` = ? ' . - 'WHERE `feeds`.`user_id` = ? ' . - 'AND (`feeds`.`folder_id` IS NULL ' . - 'OR `folders`.`deleted_at` = 0 ' . - ') ' . - 'AND `feeds`.`deleted_at` = 0 ' . - 'GROUP BY `feeds`.`id` ' . - ') `item_numbers` ' . - 'ON `item_numbers`.`id` = `feeds`.`id` '; - $params = [true, $userId]; - - return $this->findEntities($sql, $params); - } - - - public function findAll(): array - { - $sql = 'SELECT `feeds`.*, `item_numbers`.`unread_count` ' . - 'FROM `*PREFIX*news_feeds` `feeds` ' . - 'JOIN ( ' . - 'SELECT `feeds`.`id`, COUNT(`items`.`id`) AS `unread_count` ' . - 'FROM `*PREFIX*news_feeds` `feeds` ' . - 'LEFT OUTER JOIN `*PREFIX*news_folders` `folders` ' . - 'ON `feeds`.`folder_id` = `folders`.`id` ' . - 'LEFT JOIN `*PREFIX*news_items` `items` ' . - 'ON `feeds`.`id` = `items`.`feed_id` ' . - // WARNING: this is a desperate attempt at making this query - // work because prepared statements dont work. This is a - // POSSIBLE SQL INJECTION RISK WHEN MODIFIED WITHOUT THOUGHT. - // think twice when changing this - 'AND `items`.`unread` = ? ' . - 'WHERE (`feeds`.`folder_id` IS NULL ' . - 'OR `folders`.`deleted_at` = 0 ' . - ') ' . - 'AND `feeds`.`deleted_at` = 0 ' . - 'GROUP BY `feeds`.`id` ' . - ') `item_numbers` ' . - 'ON `item_numbers`.`id` = `feeds`.`id` '; - - return $this->findEntities($sql, [true]); - } - - - public function findByUrlHash($hash, $userId) - { - $sql = 'SELECT `feeds`.*, `item_numbers`.`unread_count` ' . - 'FROM `*PREFIX*news_feeds` `feeds` ' . - 'JOIN ( ' . - |