Skip to content

Commit

Permalink
fix(search): handle removed files gracefully
Browse files Browse the repository at this point in the history
When a result is found in the index
but the corresponding file does not exist in the storage anymore
skip the result and return the other search results.

Fixes #873.

Signed-off-by: Max <max@nextcloud.com>
  • Loading branch information
max-nextcloud committed Sep 13, 2023
1 parent 6b7ba6e commit 17a2152
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 5 deletions.
12 changes: 7 additions & 5 deletions lib/Search/PageContentProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,18 +109,20 @@ public function search(IUser $user, ISearchQuery $query): SearchResult {
try {
$collectiveRoot = $this->pageService->getCollectiveFolder($collective->getId(), $user->getUID());
$results = $this->indexedSearchService->searchCollective($collective, $query->getTerm());
foreach ($results as $fileId => $fileData) {
$file = $collectiveRoot->getById($fileId);
$pages[$fileId] = reset($file);
$collectiveMap[$fileId] = $collective;
}
} catch (FileSearchException|NotFoundException $e) {
$this->logger->warning('Collectives file content search failed.', [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
continue;
}
foreach ($results as $fileId => $fileData) {
$fileEntries = $collectiveRoot->getById($fileId);
if (!empty($fileEntries)) {
$pages[$fileId] = $fileEntries[0];
$collectiveMap[$fileId] = $collective;
}
}
}

$highlighter = new Highlighter((new FileSearcher())->getTokenizer());
Expand Down
89 changes: 89 additions & 0 deletions tests/Unit/Search/PageContentProviderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

namespace Unit\Service;

use OC\Files\Node\Folder;
use OC\Search\SearchQuery;
use OCA\Collectives\Db\Collective;
use OCA\Collectives\Search\PageContentProvider;
use OCA\Collectives\Service\CollectiveHelper;
use OCA\Collectives\Service\PageService;
use OCA\Collectives\Service\SearchService;
use OCP\App\IAppManager;
use OCP\IL10N;
use OCP\IURLGenerator;
use OCP\IUser;
use OCP\Search\ISearchQuery;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;

class PageContentProviderTest extends TestCase {
private PageContentProvider $provider;

protected function setUp(): void {
$collective = new Collective();
$collective->setId(123);

/** @var IL10N&MockObject $l10n */
$l10n = $this->createMock(IL10N::class);
/** @var IURLGenerator&MockObject $urlGenerator */
$urlGenerator = $this->createMock(IURLGenerator::class);
/** @var CollectiveHelper&MockObject $collectiveHelper */
$collectiveHelper = $this->createMock(CollectiveHelper::class);
$collectiveHelper->method('getCollectivesForUser')
->willReturn([$collective]);
/** @var Folder&MockObject $folder */
$folder = $this->createMock(Folder::class);
$folder->method('getById')
->willReturn([]);
/** @var PageService&MockObject $pageService */
$pageService = $this->createMock(PageService::class);
$pageService->method('getCollectiveFolder')
->willReturn($folder);
/** @var SearchService&MockObject $indexedSearchService */
$indexedSearchService = $this->createMock(SearchService::class);
$indexedSearchService->method('searchCollective')
->willReturn(array(404 => 'fileData'));
/** @var LoggerInterface&MockObject $logger */
$logger = $this->createMock(LoggerInterface::class);
/** @var IAppManager&MockObject $appManager */
$appManager = $this->createMock(IAppManager::class);
$appManager->method('isEnabledForUser')
->willReturn(true);

$this->provider = new PageContentProvider(
$l10n,
$urlGenerator,
$collectiveHelper,
$pageService,
$indexedSearchService,
$logger,
$appManager
);
}

public function testId(): void {
$this->assertEquals('collectives-page-content', $this->provider->getId());
}

public function testSearchWithMissingFile(): void {
/** @var IUser&MockObject $user */
$user = $this->createMock(IUser::class);
$user->method('getUID')
->willReturn('jane');
$query = new SearchQuery(
'Search me!',
ISearchQuery::SORT_DATE_DESC,
SearchQuery::LIMIT_DEFAULT,
null,
'collectives.'
);
$response = json_encode($this->provider->search($user, $query));
$result = json_decode($response, true);

$this->assertEquals('[]',
json_encode($result['entries'])
);
}
}

0 comments on commit 17a2152

Please sign in to comment.