diff --git a/lib/Reference/BoardReferenceProvider.php b/lib/Reference/BoardReferenceProvider.php index 62f0a7362..31932bd6f 100644 --- a/lib/Reference/BoardReferenceProvider.php +++ b/lib/Reference/BoardReferenceProvider.php @@ -55,8 +55,8 @@ class BoardReferenceProvider implements IReferenceProvider { $startIndex = $this->urlGenerator->getAbsoluteURL('/index.php/apps/' . Application::APP_ID); // link example: https://nextcloud.local/index.php/apps/deck/#/board/2 - $noIndexMatch = preg_match('/^' . preg_quote($start, '/') . '\/#\/board\/[0-9]+$/', $referenceText) === 1; - $indexMatch = preg_match('/^' . preg_quote($startIndex, '/') . '\/#\/board\/[0-9]+$/', $referenceText) === 1; + $noIndexMatch = preg_match('/^' . preg_quote($start, '/') . '(?:\/#!?)?\/board\/[0-9]+$/', $referenceText) === 1; + $indexMatch = preg_match('/^' . preg_quote($startIndex, '/') . '(?:\/#!?)?\/board\/[0-9]+$/', $referenceText) === 1; return $noIndexMatch || $indexMatch; } @@ -108,9 +108,9 @@ class BoardReferenceProvider implements IReferenceProvider { $start = $this->urlGenerator->getAbsoluteURL('/apps/' . Application::APP_ID); $startIndex = $this->urlGenerator->getAbsoluteURL('/index.php/apps/' . Application::APP_ID); - preg_match('/^' . preg_quote($start, '/') . '\/#\/board\/([0-9]+)$/', $url, $matches); + preg_match('/^' . preg_quote($start, '/') . '(?:\/#!?)?\/board\/([0-9]+)$/', $url, $matches); if (!$matches) { - preg_match('/^' . preg_quote($startIndex, '/') . '\/#\/board\/([0-9]+)$/', $url, $matches); + preg_match('/^' . preg_quote($startIndex, '/') . '(?:\/#!?)?\/board\/([0-9]+)$/', $url, $matches); } if ($matches && count($matches) > 1) { return (int) $matches[1]; diff --git a/lib/Reference/CardReferenceProvider.php b/lib/Reference/CardReferenceProvider.php index f3dcac5cd..d11e83e74 100644 --- a/lib/Reference/CardReferenceProvider.php +++ b/lib/Reference/CardReferenceProvider.php @@ -108,8 +108,8 @@ class CardReferenceProvider extends ADiscoverableReferenceProvider implements IS $startIndex = $this->urlGenerator->getAbsoluteURL('/index.php/apps/' . Application::APP_ID); // link example: https://nextcloud.local/index.php/apps/deck/#/board/2/card/11 - $noIndexMatchFull = preg_match('/^' . preg_quote($start, '/') . '\/#\/board\/[0-9]+\/card\/[0-9]+$/', $referenceText) === 1; - $indexMatchFull = preg_match('/^' . preg_quote($startIndex, '/') . '\/#\/board\/[0-9]+\/card\/[0-9]+$/', $referenceText) === 1; + $noIndexMatchFull = preg_match('/^' . preg_quote($start, '/') . '(?:\/#!?)?\/board\/[0-9]+\/card\/[0-9]+$/', $referenceText) === 1; + $indexMatchFull = preg_match('/^' . preg_quote($startIndex, '/') . '(?:\/#!?)?\/board\/[0-9]+\/card\/[0-9]+$/', $referenceText) === 1; // link example: https://nextcloud.local/index.php/apps/deck/card/11 $noIndexMatch = preg_match('/^' . preg_quote($start, '/') . '\/card\/[0-9]+$/', $referenceText) === 1; @@ -125,16 +125,17 @@ class CardReferenceProvider extends ADiscoverableReferenceProvider implements IS if ($this->matchReference($referenceText)) { $ids = $this->getBoardCardId($referenceText); if ($ids !== null) { - [$boardId, $cardId] = $ids; + [, $cardId] = $ids; try { $card = $this->cardService->find((int) $cardId)->jsonSerialize(); $stack = $this->stackService->find((int) $card['stackId'])->jsonSerialize(); - $board = $this->boardService->find((int)($boardId ?? $stack['boardId']))->jsonSerialize(); + $board = $this->boardService->find((int) $stack['boardId'])->jsonSerialize(); } catch (NoPermissionException $e) { // Skip throwing if user has no permissions return null; } + $boardId = $board['id']; $card = $this->sanitizeSerializedCard($card); $board = $this->sanitizeSerializedBoard($board); @@ -159,14 +160,14 @@ class CardReferenceProvider extends ADiscoverableReferenceProvider implements IS $result = $cardDetails->jsonSerialize(); unset($result['assignedUsers']); return $result; - }, $stack['cards']); + }, $stack['cards'] ?? []); return $stack; } private function sanitizeSerializedBoard(array $board): array { unset($board['labels']); - $board['owner'] = $board['owner']->jsonSerialize(); + $board['owner'] = $board['owner']?->jsonSerialize(); unset($board['acl']); unset($board['users']); @@ -176,18 +177,18 @@ class CardReferenceProvider extends ADiscoverableReferenceProvider implements IS private function sanitizeSerializedCard(array $card): array { $card['labels'] = array_map(function (Label $label) { return $label->jsonSerialize(); - }, $card['labels']); + }, $card['labels'] ?? []); $card['assignedUsers'] = array_map(function (Assignment $assignment) { $result = $assignment->jsonSerialize(); $result['participant'] = $result['participant']->jsonSerialize(); return $result; - }, $card['assignedUsers']); - $card['owner'] = $card['owner']->jsonSerialize(); + }, $card['assignedUsers'] ?? []); + $card['owner'] = $card['owner']?->jsonSerialize() ?? $card['owner']; unset($card['relatedStack']); unset($card['relatedBoard']); $card['attachments'] = array_map(function (Attachment $attachment) { return $attachment->jsonSerialize(); - }, $card['attachments']); + }, $card['attachments'] ?? []); return $card; } @@ -196,12 +197,12 @@ class CardReferenceProvider extends ADiscoverableReferenceProvider implements IS $start = $this->urlGenerator->getAbsoluteURL('/apps/' . Application::APP_ID); $startIndex = $this->urlGenerator->getAbsoluteURL('/index.php/apps/' . Application::APP_ID); - preg_match('/^' . preg_quote($start, '/') . '\/#\/board\/([0-9]+)\/card\/([0-9]+)$/', $url, $matches); + preg_match('/^' . preg_quote($start, '/') . '(?:\/#!?)?\/board\/([0-9]+)\/card\/([0-9]+)$/', $url, $matches); if ($matches && count($matches) > 2) { return [$matches[1], $matches[2]]; } - preg_match('/^' . preg_quote($startIndex, '/') . '\/#\/board\/([0-9]+)\/card\/([0-9]+)$/', $url, $matches2); + preg_match('/^' . preg_quote($startIndex, '/') . '(?:\/#!?)?\/board\/([0-9]+)\/card\/([0-9]+)$/', $url, $matches2); if ($matches2 && count($matches2) > 2) { return [$matches2[1], $matches2[2]]; } diff --git a/tests/unit/Reference/CardReferenceProviderTest.php b/tests/unit/Reference/CardReferenceProviderTest.php index 3824d98af..de2ac1362 100644 --- a/tests/unit/Reference/CardReferenceProviderTest.php +++ b/tests/unit/Reference/CardReferenceProviderTest.php @@ -22,6 +22,9 @@ namespace Reference; +use OCA\Deck\Db\Board; +use OCA\Deck\Db\Card; +use OCA\Deck\Db\Stack; use OCA\Deck\Reference\CardReferenceProvider; use OCA\Deck\Service\BoardService; use OCA\Deck\Service\CardService; @@ -51,16 +54,55 @@ class CardReferenceProviderTest extends TestCase { ); } - public function testUrl() { + public static function dataUrl(): array { + return [ + ['https://nextcloud.com', null], + ['https://localhost/apps/deck/#!/board/2/card/11', 11], + ['https://localhost/index.php/apps/deck/#!/board/2/card/11', 11], + ['https://localhost/apps/deck/#/board/2/card/11', 11], + ['https://localhost/index.php/apps/deck/#/board/2/card/11', 11], + ['https://localhost/apps/deck/board/2/card/11', 11], + ['https://localhost/index.php/apps/deck/board/2/card/11', 11], + ['https://localhost/apps/deck/card/11', 11], + ['https://localhost/index.php/apps/deck/card/11', 11], + ]; + } + + /** + * @dataProvider dataUrl + */ + public function testUrl($url, $id) { $this->urlGenerator->expects($this->any()) ->method('getAbsoluteURL') ->willReturnCallback(function ($path) { return 'https://localhost/' . ltrim($path, '/'); }); - self::assertFalse($this->provider->matchReference('https://nextcloud.com')); - self::assertTrue($this->provider->matchReference('https://localhost/apps/deck/#/board/2/card/11')); - self::assertTrue($this->provider->matchReference('https://localhost/index.php/apps/deck/#/board/2/card/11')); - self::assertTrue($this->provider->matchReference('https://localhost/apps/deck/card/11')); - self::assertTrue($this->provider->matchReference('https://localhost/index.php/apps/deck/card/11')); + $matchExpect = $id !== null; + self::assertEquals($matchExpect, $this->provider->matchReference($url)); + + $card = Card::fromRow([ + 'id' => $id, + 'stackId' => 1234, + ]); + $stack = Stack::fromRow([ + 'boardId' => 9876, + ]); + $board = Board::fromRow([ + 'id' => 9876, + ]); + + $this->cardService->method('find')->with($id)->willReturn($card); + $this->stackService->method('find')->with(1234)->willReturn($stack); + $this->boardService->method('find')->with(9876)->willReturn($board); + + $reference = $this->provider->resolveReference($url); + + if ($id !== null) { + self::assertEquals($id, $reference->jsonSerialize()['richObject']['card']['id']); + self::assertEquals(9876, $reference->jsonSerialize()['richObject']['board']['id']); + + } else { + self::assertNull($reference); + } } }