From fd01e9ad7b60081c1b4e54a42580987f3636f6cd Mon Sep 17 00:00:00 2001 From: Sean Molenaar Date: Tue, 8 Jun 2021 18:05:27 +0200 Subject: Search: add feed search Signed-off-by: Sean Molenaar --- CHANGELOG.md | 1 + lib/AppInfo/Application.php | 28 +----- lib/Search/FeedSearchProvider.php | 79 ++++++++++++++++ tests/Unit/Search/FeedSearchProviderTest.php | 130 +++++++++++++++++++++++++++ 4 files changed, 212 insertions(+), 26 deletions(-) create mode 100644 lib/Search/FeedSearchProvider.php create mode 100644 tests/Unit/Search/FeedSearchProviderTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 8fe49f304..4d2c04f9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ The format is almost based on [Keep a Changelog](https://keepachangelog.com/en/1 ## [16.x.x] ### Changed +- added feed search (#1402) ### Fixed - removed reference for deleted repair-steps (#1399) ## [15.x.x] diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index ea7beeae5..55f9b0ff5 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -19,9 +19,9 @@ use HTMLPurifier; use HTMLPurifier_Config; use Favicon\Favicon; -use OCA\News\Config\LegacyConfig; use OCA\News\Config\FetcherConfig; use OCA\News\Hooks\UserDeleteHook; +use OCA\News\Search\FeedSearchProvider; use OCA\News\Search\FolderSearchProvider; use OCP\AppFramework\Bootstrap\IBootContext; @@ -29,8 +29,6 @@ use OCP\AppFramework\Bootstrap\IBootstrap; use OCP\AppFramework\Bootstrap\IRegistrationContext; use OCP\ITempManager; use OCP\AppFramework\App; -use OCP\Files\IRootFolder; -use OCP\Files\Node; use OCA\News\Fetcher\FeedFetcher; use OCA\News\Fetcher\Fetcher; @@ -83,12 +81,12 @@ class Application extends App implements IBootstrap }); $context->registerSearchProvider(FolderSearchProvider::class); + $context->registerSearchProvider(FeedSearchProvider::class); $context->registerEventListener(BeforeUserDeletedEvent::class, UserDeleteHook::class); // parameters $context->registerParameter('exploreDir', __DIR__ . '/../Explore/feeds'); - $context->registerParameter('configFile', 'config.ini'); $context->registerService(HTMLPurifier::class, function (ContainerInterface $c): HTMLPurifier { $directory = $c->get(ITempManager::class)->getTempBaseDir() . '/news/cache/purifier'; @@ -142,28 +140,6 @@ class Application extends App implements IBootstrap $favicon->cache(['dir' => $c->get(ITempManager::class)->getTempBaseDir()]); return $favicon; }); - - //TODO: Remove code after 15.1 - $context->registerService('ConfigFolder', function (ContainerInterface $c): ?Node { - /** @var IRootFolder $fs */ - $fs = $c->get(IRootFolder::class); - $path = 'news/config'; - if ($fs->nodeExists($path)) { - return $fs->get($path); - } else { - return null; - } - }); - - //TODO: Remove code after 15.1 - $context->registerService(LegacyConfig::class, function (ContainerInterface $c): LegacyConfig { - $config = new LegacyConfig( - $c->get('ConfigFolder'), - $c->get(LoggerInterface::class) - ); - $config->read($c->get('configFile'), false); - return $config; - }); } public function boot(IBootContext $context): void diff --git a/lib/Search/FeedSearchProvider.php b/lib/Search/FeedSearchProvider.php new file mode 100644 index 000000000..bbcd466e4 --- /dev/null +++ b/lib/Search/FeedSearchProvider.php @@ -0,0 +1,79 @@ +l10n = $l10n; + $this->urlGenerator = $urlGenerator; + $this->service = $service; + } + + public function getId(): string + { + return 'news_feed'; + } + + public function getName(): string + { + return $this->l10n->t('News feeds'); + } + + public function getOrder(string $route, array $routeParameters): int + { + if ($route === 'news.page.index') { + // Active app, prefer my results + return -1; + } + + return 60; + } + + public function search(IUser $user, ISearchQuery $query): SearchResult + { + $list = []; + $term = strtolower($query->getTerm()); + + foreach ($this->service->findAllForUser($user->getUID()) as $feed) { + if (strpos(strtolower($feed->getTitle()), $term) === false) { + continue; + } + + $list[] = new SearchResultEntry( + $this->urlGenerator->imagePath('core', 'filetypes/text.svg'), + $feed->getTitle(), + $this->l10n->t('Unread articles') . ': ' . $feed->getUnreadCount(), + $this->urlGenerator->linkToRoute('news.page.index') . '#/items/feeds/' . $feed->getId() + ); + } + + return SearchResult::complete($this->l10n->t('News'), $list); + } +} diff --git a/tests/Unit/Search/FeedSearchProviderTest.php b/tests/Unit/Search/FeedSearchProviderTest.php new file mode 100644 index 000000000..97ec1f984 --- /dev/null +++ b/tests/Unit/Search/FeedSearchProviderTest.php @@ -0,0 +1,130 @@ +l10n = $this->getMockBuilder(IL10N::class) + ->disableOriginalConstructor() + ->getMock(); + $this->generator = $this->getMockBuilder(IURLGenerator::class) + ->disableOriginalConstructor() + ->getMock(); + $this->folderService = $this->getMockBuilder(FeedServiceV2::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->class = new FeedSearchProvider( + $this->l10n, + $this->generator, + $this->folderService + ); + } + + public function testGetId() + { + $this->assertSame('news_feed', $this->class->getId()); + } + + public function testGetName() + { + $this->l10n->expects($this->once()) + ->method('t') + ->with('News feeds') + ->willReturnArgument(0); + + $this->assertSame('News feeds', $this->class->getName()); + } + + public function testGetOrderExternal() + { + $this->assertSame(60, $this->class->getOrder('contacts.Page.index', [])); + } + + public function testGetOrderInternal() + { + $this->assertSame(-1, $this->class->getOrder('news.page.index', [])); + } + + public function testSearch() + { + $user = $this->getMockBuilder(IUser::class) + ->getMock(); + $query = $this->getMockBuilder(ISearchQuery::class) + ->getMock(); + + $user->expects($this->once()) + ->method('getUID') + ->willReturn('user'); + + $query->expects($this->once()) + ->method('getTerm') + ->willReturn('Term'); + + $folders = [ + Feed::fromRow(['id' => 1,'title' => 'some_tErm', 'unread_count'=> 1]), + Feed::fromRow(['id' => 2,'title' => 'nothing', 'unread_count'=> 1]) + ]; + + $this->folderService->expects($this->once()) + ->method('findAllForUser') + ->with('user') + ->willReturn($folders); + + $this->l10n->expects($this->exactly(2)) + ->method('t') + ->withConsecutive(['Unread articles'], ['News']) + ->willReturnArgument(0); + + $this->generator->expects($this->once()) + ->method('imagePath') + ->with('core', 'filetypes/text.svg') + ->willReturn('folderpath.svg'); + + $this->generator->expects($this->once()) + ->method('linkToRoute') + ->with('news.page.index') + ->willReturn('/news'); + + + $result = $this->class->search($user, $query)->jsonSerialize(); + $entry = $result['entries'][0]->jsonSerialize(); + $this->assertSame('News', $result['name']); + $this->assertSame('some_tErm', $entry['title']); + $this->assertSame('folderpath.svg', $entry['thumbnailUrl']); + $this->assertSame('Unread articles: 1', $entry['subline']); + $this->assertSame('/news#/items/feeds/1', $entry['resourceUrl']); + } +} -- cgit v1.2.3