From a0ab7a257858b305434255df2f33ef4b323ac81d Mon Sep 17 00:00:00 2001 From: Joas Schilling Date: Thu, 13 Aug 2015 10:57:08 +0200 Subject: [PATCH] Add all possible links next, prev, first and last --- apps/files_sharing/api/sharees.php | 54 +++++++++++++++++------- apps/files_sharing/tests/api/sharees.php | 50 +++++++++++++++++++++- 2 files changed, 88 insertions(+), 16 deletions(-) diff --git a/apps/files_sharing/api/sharees.php b/apps/files_sharing/api/sharees.php index de5f9c8cbf..714b4950c5 100644 --- a/apps/files_sharing/api/sharees.php +++ b/apps/files_sharing/api/sharees.php @@ -285,7 +285,6 @@ class Sharees { //Pagination $start = ($page - 1) * $perPage; - $end = $page * $perPage; $total = sizeof($sharees); $sharees = array_slice($sharees, $start, $perPage); @@ -294,18 +293,16 @@ class Sharees { $response->setTotalItems($total); $response->setItemsPerPage($perPage); - if ($total > $end) { - $params = [ - 'search' => $search, - 'itemType' => $itemType, - 'existingShares' => $existingShares, - 'shareType' => $shareTypes, - 'page' => $page + 1, - 'limit' => $perPage, - ]; + $links = $this->getPaginationLinks($page, $total, [ + 'search' => $search, + 'itemType' => $itemType, + 'existingShares' => $existingShares, + 'shareType' => $shareTypes, + 'limit' => $perPage, + ]); - $url = $this->urlGenerator->getAbsoluteURL('/ocs/v1.php/apps/files_sharing/api/v1/sharees') . '?' . http_build_query($params); - $response->addHeader('Link', '<' . $url . '> rel="next"'); + if (!empty($links)) { + $response->addHeader('Link', implode(', ', $links)); } return $response; @@ -319,10 +316,37 @@ class Sharees { * @return array */ protected function filterSharees($potentialSharees, $existingSharees) { - $sharees = array_map(function ($sharee) use ($existingSharees) { + $sharees = array_filter($potentialSharees, function ($sharee) use ($existingSharees) { return in_array($sharee['value']['shareWith'], $existingSharees) ? null : $sharee; - }, $potentialSharees); + }); - return array_filter($sharees); + return $sharees; + } + + /** + * Generates a bunch of pagination links for the current page + * + * @param int $page Current page + * @param int $total Number of total items that need to be paginated + * @param array $params Parameters for the URL + * @return array + */ + protected function getPaginationLinks($page, $total, array $params) { + $url = $this->urlGenerator->getAbsoluteURL('/ocs/v1.php/apps/files_sharing/api/v1/sharees') . '?'; + + $links = []; + if ($page > 1) { + $params['page'] = 1; + $links[] = '<' . $url . http_build_query($params) . '>; rel="first"'; + $params['page'] = $page - 1; + $links[] = '<' . $url . http_build_query($params) . '>; rel="prev"'; + } + if ($page * $params['limit'] < $total) { + $params['page'] = $page + 1; + $links[] = '<' . $url . http_build_query($params) . '>; rel="next"'; + $params['page'] = ceil($total / $params['limit']); + $links[] = '<' . $url . http_build_query($params) . '>; rel="last"'; + } + return $links; } } diff --git a/apps/files_sharing/tests/api/sharees.php b/apps/files_sharing/tests/api/sharees.php index ec19036bb8..7efd29e592 100644 --- a/apps/files_sharing/tests/api/sharees.php +++ b/apps/files_sharing/tests/api/sharees.php @@ -672,7 +672,7 @@ class ShareesTest extends TestCase { $headers = $ocs->getHeaders(); $this->assertArrayHasKey('Link', $headers); $this->assertStringStartsWith('<', $headers['Link']); - $this->assertStringEndsWith('> rel="next"', $headers['Link']); + $this->assertStringEndsWith('"', $headers['Link']); } } @@ -735,4 +735,52 @@ class ShareesTest extends TestCase { public function testFilterSharees($potentialSharees, $existingSharees, $expectedSharees) { $this->assertEquals($expectedSharees, $this->invokePrivate($this->sharees, 'filterSharees', [$potentialSharees, $existingSharees])); } + + public function dataGetPaginationLinks() { + return [ + [1, 1, ['limit' => 2], []], + [1, 3, ['limit' => 2], [ + '; rel="next"', + '; rel="last"', + ]], + [1, 21, ['limit' => 2], [ + '; rel="next"', + '; rel="last"', + ]], + [2, 21, ['limit' => 2], [ + '; rel="first"', + '; rel="prev"', + '; rel="next"', + '; rel="last"', + ]], + [5, 21, ['limit' => 2], [ + '; rel="first"', + '; rel="prev"', + '; rel="next"', + '; rel="last"', + ]], + [10, 21, ['limit' => 2], [ + '; rel="first"', + '; rel="prev"', + '; rel="next"', + '; rel="last"', + ]], + [11, 21, ['limit' => 2], [ + '; rel="first"', + '; rel="prev"', + ]], + ]; + } + + /** + * @dataProvider dataGetPaginationLinks + * + * @param int $page + * @param int $total + * @param array $params + * @param array $expected + */ + public function testGetPaginationLinks($page, $total, $params, $expected) { + $this->assertEquals($expected, $this->invokePrivate($this->sharees, 'getPaginationLinks', [$page, $total, $params])); + } }