Skip to content

Commit

Permalink
use distinct pagination cursor for cards and boards, use cursor and l…
Browse files Browse the repository at this point in the history
…imit in SearchSe

rvice::searchBoards()

Signed-off-by: Julien Veyssier <[email protected]>
  • Loading branch information
Julien Veyssier committed Oct 4, 2021
1 parent ede6a05 commit b533d11
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 19 deletions.
78 changes: 62 additions & 16 deletions lib/Search/DeckProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,29 +63,52 @@ public function getName(): string {
}

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);

$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 (count($cardResults) < $query->getLimit()) {
// 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
);
}

Expand All @@ -95,4 +118,27 @@ public function getOrder(string $route, array $routeParameters): int {
}
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) ?: '');
}
}
21 changes: 18 additions & 3 deletions lib/Service/SearchService.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public function searchCards(string $term, int $limit = null, ?int $cursor = null
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);
Expand All @@ -91,9 +91,24 @@ public function searchCards(string $term, int $limit = null, ?int $cursor = null

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 {
Expand Down

0 comments on commit b533d11

Please sign in to comment.