use distinct pagination cursor for cards and boards, use cursor and limit in SearchService::searchBoards()
Signed-off-by: Julien Veyssier <eneiluj@posteo.net>
This commit is contained in:
@@ -63,29 +63,52 @@ class DeckProvider implements IProvider {
|
||||
}
|
||||
|
||||
public function search(IUser $user, ISearchQuery $query): SearchResult {
|
||||
$cursor = $query->getCursor() !== null ? (int)$query->getCursor() : null;
|
||||
$boardResults = $this->searchService->searchBoards($query->getTerm(), $query->getLimit(), $cursor);
|
||||
$cardResults = $this->searchService->searchCards($query->getTerm(), $query->getLimit(), $cursor);
|
||||
$results = array_merge(
|
||||
array_map(function (Board $board) {
|
||||
return new BoardSearchResultEntry($board, $this->urlGenerator);
|
||||
}, $boardResults),
|
||||
array_map(function (Card $card) {
|
||||
return new CardSearchResultEntry($card->getRelatedBoard(), $card->getRelatedStack(), $card, $this->urlGenerator);
|
||||
}, $cardResults)
|
||||
);
|
||||
$cursor = $query->getCursor();
|
||||
[$boardCursor, $cardCursor] = $this->parseCursor($cursor);
|
||||
|
||||
if (count($cardResults) < $query->getLimit()) {
|
||||
$boardObjects = $this->searchService->searchBoards($query->getTerm(), $query->getLimit(), $boardCursor);
|
||||
$boardResults = array_map(function (Board $board) {
|
||||
return [
|
||||
'object' => $board,
|
||||
'entry' => new BoardSearchResultEntry($board, $this->urlGenerator)
|
||||
];
|
||||
}, $boardObjects);
|
||||
|
||||
$cardObjects = $this->searchService->searchCards($query->getTerm(), $query->getLimit(), $cardCursor);
|
||||
$cardResults = array_map(function (Card $card) {
|
||||
return [
|
||||
'object' => $card,
|
||||
'entry' => new CardSearchResultEntry($card->getRelatedBoard(), $card->getRelatedStack(), $card, $this->urlGenerator)
|
||||
];
|
||||
}, $cardObjects);
|
||||
|
||||
$results = array_merge($boardResults, $cardResults);
|
||||
|
||||
usort($results, function ($a, $b) {
|
||||
$ta = $a['object']->getLastModified();
|
||||
$tb = $b['object']->getLastModified();
|
||||
return $ta === $tb
|
||||
? 0
|
||||
: ($ta > $tb ? -1 : 1);
|
||||
});
|
||||
|
||||
$resultEntries = array_map(function (array $result) {
|
||||
return $result['entry'];
|
||||
}, $results);
|
||||
|
||||
// if both cards and boards results are less then the limit, we know we won't get more
|
||||
if (count($resultEntries) < $query->getLimit()) {
|
||||
return SearchResult::complete(
|
||||
'Deck',
|
||||
$results
|
||||
$resultEntries
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
$newCursor = $this->getNewCursor($boardObjects, $cardObjects);
|
||||
return SearchResult::paginated(
|
||||
'Deck',
|
||||
$results,
|
||||
$cardResults[count($results) - 1]->getLastModified()
|
||||
$resultEntries,
|
||||
$newCursor
|
||||
);
|
||||
}
|
||||
|
||||
@@ -95,4 +118,27 @@ class DeckProvider implements IProvider {
|
||||
}
|
||||
return 10;
|
||||
}
|
||||
|
||||
private function parseCursor(?string $cursor): array {
|
||||
$boardCursor = null;
|
||||
$cardCursor = null;
|
||||
if ($cursor !== null) {
|
||||
$splitCursor = explode('|', $cursor);
|
||||
if (count($splitCursor) >= 2) {
|
||||
$boardCursor = (int)$splitCursor[0] ?: null;
|
||||
$cardCursor = (int)$splitCursor[1] ?: null;
|
||||
}
|
||||
}
|
||||
return [$boardCursor, $cardCursor];
|
||||
}
|
||||
|
||||
private function getNewCursor(array $boards, array $cards): string {
|
||||
$boardTimestamps = array_map(function (Board $board) {
|
||||
return $board->getLastModified();
|
||||
}, $boards);
|
||||
$cardTimestamps = array_map(function (Card $card) {
|
||||
return $card->getLastModified();
|
||||
}, $cards);
|
||||
return (min($boardTimestamps) ?: '') . '|' . (min($cardTimestamps) ?: '');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ class SearchService {
|
||||
return $board->getId();
|
||||
}, $boards);
|
||||
$matchedCards = $this->cardMapper->search($boardIds, $this->filterStringParser->parse($term), $limit, $cursor);
|
||||
|
||||
|
||||
$self = $this;
|
||||
return array_map(function (Card $card) use ($self) {
|
||||
$self->cardService->enrich($card);
|
||||
@@ -91,9 +91,24 @@ class SearchService {
|
||||
|
||||
public function searchBoards(string $term, ?int $limit, ?int $cursor): array {
|
||||
$boards = $this->boardService->getUserBoards();
|
||||
return array_filter($boards, static function (Board $board) use ($term) {
|
||||
return mb_stripos(mb_strtolower($board->getTitle()), mb_strtolower($term)) > -1;
|
||||
// get boards that have a lastmodified date which is lower than the cursor
|
||||
// and which match the search term
|
||||
$filteredBoards = array_filter($boards, static function (Board $board) use ($term, $cursor) {
|
||||
return (
|
||||
($cursor === null || $board->getLastModified() < $cursor)
|
||||
&& mb_stripos(mb_strtolower($board->getTitle()), mb_strtolower($term)) > -1
|
||||
);
|
||||
});
|
||||
// sort the boards, recently modified first
|
||||
usort($filteredBoards, function ($boardA, $boardB) {
|
||||
$ta = $boardA->getLastModified();
|
||||
$tb = $boardB->getLastModified();
|
||||
return $ta === $tb
|
||||
? 0
|
||||
: ($ta > $tb ? -1 : 1);
|
||||
});
|
||||
// limit the number of results
|
||||
return array_slice($filteredBoards, 0, $limit);
|
||||
}
|
||||
|
||||
public function searchComments(string $term, ?int $limit = null, ?int $cursor = null): array {
|
||||
|
||||
Reference in New Issue
Block a user