From 2059e55e30957dfcbebe5dfa3e89a5dc7ea5bf17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julius=20H=C3=A4rtl?= Date: Mon, 17 Aug 2020 17:13:17 +0200 Subject: [PATCH] Implement new unified search API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Julius Härtl --- lib/Db/CardMapper.php | 17 +++- lib/Search/BoardSearchResultEntry.php | 43 ++++++++++ lib/Search/CardSearchResultEntry.php | 8 +- lib/Search/DeckProvider.php | 119 ++++++++++++++++++++++++++ lib/Service/CardService.php | 5 ++ 5 files changed, 186 insertions(+), 6 deletions(-) create mode 100644 lib/Search/BoardSearchResultEntry.php create mode 100644 lib/Search/DeckProvider.php diff --git a/lib/Db/CardMapper.php b/lib/Db/CardMapper.php index 27c846e57..502dafe48 100644 --- a/lib/Db/CardMapper.php +++ b/lib/Db/CardMapper.php @@ -230,10 +230,21 @@ public function findUnexposedDescriptionChances() { return $this->findEntities($qb); } - public function search($boardIds, $term) { + public function search($boardIds, $term, $limit = null, $offset = null) { $qb = $this->queryCardsByBoards($boardIds); - $qb->andWhere($qb->expr()->iLike('c.title', $qb->createNamedParameter('%' . $this->db->escapeLikeParameter($term) . '%'))); - $qb->setMaxResults(10); + $qb->andWhere($qb->expr()->eq('c.deleted_at', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT))); + $qb->andWhere( + $qb->expr()->orX( + $qb->expr()->iLike('c.title', $qb->createNamedParameter('%' . $this->db->escapeLikeParameter($term) . '%')), + $qb->expr()->iLike('c.description', $qb->createNamedParameter('%' . $this->db->escapeLikeParameter($term) . '%')) + ) + ); + if ($limit !== null) { + $qb->setMaxResults($limit); + } + if ($offset !== null) { + $qb->setFirstResult($offset); + } return $this->findEntities($qb); } diff --git a/lib/Search/BoardSearchResultEntry.php b/lib/Search/BoardSearchResultEntry.php new file mode 100644 index 000000000..7d9ffb3f6 --- /dev/null +++ b/lib/Search/BoardSearchResultEntry.php @@ -0,0 +1,43 @@ + + * + * @author Julius Härtl + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +declare(strict_types=1); + + +namespace OCA\Deck\Search; + + +use OCA\Deck\Db\Board; +use OCP\Search\SearchResultEntry; + +class BoardSearchResultEntry extends SearchResultEntry { + + public function __construct(Board $board, $urlGenerator) { + parent::__construct( + '', + $board->getTitle(), + '', + $urlGenerator->linkToRoute('deck.page.index') . '#/board/' . $board->getId(), + 'icon-deck'); + } +} diff --git a/lib/Search/CardSearchResultEntry.php b/lib/Search/CardSearchResultEntry.php index 7f31604c5..c3fbfede0 100644 --- a/lib/Search/CardSearchResultEntry.php +++ b/lib/Search/CardSearchResultEntry.php @@ -28,11 +28,13 @@ use OCA\Deck\Db\Board; +use OCA\Deck\Db\Card; +use OCA\Deck\Db\Stack; use OCP\Search\SearchResultEntry; -class BoardSearchResultEntry extends SearchResultEntry { +class CardSearchResultEntry extends SearchResultEntry { - public function __construct(Board $board, $urlGenerator) { - parent::__construct('', $board->getTitle(), '', $urlGenerator->linkToRoute('deck.page.index') . '#/board/' . $board->getId(), 'icon-deck'); + public function __construct(Board $board, Stack $stack, Card $card, $urlGenerator) { + parent::__construct('', $card->getTitle(), $board->getTitle() . ' » ' . $stack->getTitle() , $urlGenerator->linkToRoute('deck.page.index') . '#/board/' . $board->getId() . '/card/' . $card->getId(), 'icon-deck'); } } diff --git a/lib/Search/DeckProvider.php b/lib/Search/DeckProvider.php new file mode 100644 index 000000000..676b1e8c5 --- /dev/null +++ b/lib/Search/DeckProvider.php @@ -0,0 +1,119 @@ + + * + * @author Julius Härtl + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +declare(strict_types=1); + + +namespace OCA\Deck\Search; + + +use OCA\Deck\Db\Board; +use OCA\Deck\Db\Card; +use OCA\Deck\Db\CardMapper; +use OCA\Deck\Db\StackMapper; +use OCA\Deck\Service\BoardService; +use OCP\IURLGenerator; +use OCP\IUser; +use OCP\Search\IProvider; +use OCP\Search\ISearchQuery; +use OCP\Search\SearchResult; + +class DeckProvider implements IProvider { + + /** + * @var BoardService + */ + private $boardService; + /** + * @var CardMapper + */ + private $cardMapper; + /** + * @var StackMapper + */ + private $stackMapper; + /** + * @var IURLGenerator + */ + private $urlGenerator; + + public function __construct( + BoardService $boardService, + StackMapper $stackMapper, + CardMapper $cardMapper, + IURLGenerator $urlGenerator + ) { + $this->boardService = $boardService; + $this->stackMapper = $stackMapper; + $this->cardMapper = $cardMapper; + $this->urlGenerator = $urlGenerator; + } + + /** + * @inheritDoc + */ + public function getId(): string { + return 'deck'; + } + + public function getName(): string { + return 'Deck'; + } + + /** + * @inheritDoc + */ + public function search(IUser $user, ISearchQuery $query): SearchResult { + $boards = $this->boardService->findAll(); + $cards = $this->cardMapper->search(array_map(function (Board $board) { + return $board->getId(); + }, $boards), $query->getTerm(), $query->getLimit(), $query->getCursor()); + + $self = $this; + $results = array_merge( + array_map(function (Board $board) { + return new BoardSearchResultEntry($board, $this->urlGenerator); + }, array_filter($boards, function($board) use ($query) { + return mb_strpos($board->getTitle(), $query->getTerm()) !== -1; + })), + array_map(function (Card $card) use ($self) { + $board = $self->boardService->find($self->cardMapper->findBoardId($card->getId())); + $stack = $self->stackMapper->find($card->getStackId()); + return new CardSearchResultEntry($board, $stack, $card, $this->urlGenerator); + }, $cards) + ); + + return SearchResult::complete( + 'Deck', + $results + ); + } + + public function getOrder(string $route, array $routeParameters): int { + if ($route === 'deck.page.index') { + // Before comments + return -5; + } + return 10; + } +} diff --git a/lib/Service/CardService.php b/lib/Service/CardService.php index 9d4867705..50504bc07 100644 --- a/lib/Service/CardService.php +++ b/lib/Service/CardService.php @@ -116,6 +116,11 @@ public function fetchDeleted($boardId) { return $cards; } + public function search($boardIds, $term) { + $cards = $this->cardMapper->search($boardIds, $term); + return $cards; + } + /** * @param $cardId * @return \OCA\Deck\Db\RelationalEntity