aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorArthurHoaro <arthur@hoa.ro>2021-01-20 14:45:59 +0100
committerArthurHoaro <arthur@hoa.ro>2021-01-20 15:01:29 +0100
commit9b8c0a4560fa1d87cab1529099b1b4677e92e265 (patch)
tree330a9b1a42ff7b7f24a76612b57fae63417ef483
parent055d97f9a9e67d8ee8ae81bbf59a4b846a145d9f (diff)
downloadShaarli-9b8c0a4560fa1d87cab1529099b1b4677e92e265.tar.gz
Shaarli-9b8c0a4560fa1d87cab1529099b1b4677e92e265.tar.zst
Shaarli-9b8c0a4560fa1d87cab1529099b1b4677e92e265.zip
Handle pagination through BookmarkService
Handle all search results through SearchResult object. This is a required step toward implementing a BookmarkService based on SQL database. Related to #953
-rw-r--r--application/api/controllers/Links.php38
-rw-r--r--application/api/controllers/Tags.php8
-rw-r--r--application/bookmark/BookmarkFileService.php32
-rw-r--r--application/bookmark/BookmarkServiceInterface.php8
-rw-r--r--application/bookmark/SearchResult.php136
-rw-r--r--application/feed/FeedBuilder.php25
-rw-r--r--application/front/controller/admin/ManageTagController.php11
-rw-r--r--application/front/controller/admin/ThumbnailsController.php2
-rw-r--r--application/front/controller/visitor/BookmarkListController.php63
-rw-r--r--application/front/controller/visitor/DailyController.php2
-rw-r--r--application/front/controller/visitor/PictureWallController.php12
-rw-r--r--application/netscape/NetscapeBookmarkUtils.php2
-rw-r--r--application/updater/Updater.php2
-rw-r--r--tests/bookmark/BookmarkFileServiceTest.php8
-rw-r--r--tests/bookmark/SearchResultTest.php125
-rw-r--r--tests/front/controller/admin/ManageTagControllerTest.php9
-rw-r--r--tests/front/controller/admin/ThumbnailsControllerTest.php5
-rw-r--r--tests/front/controller/visitor/BookmarkListControllerTest.php29
-rw-r--r--tests/front/controller/visitor/DailyControllerTest.php45
-rw-r--r--tests/front/controller/visitor/PictureWallControllerTest.php7
20 files changed, 420 insertions, 149 deletions
diff --git a/application/api/controllers/Links.php b/application/api/controllers/Links.php
index b83b2260..fe4bdc9f 100644
--- a/application/api/controllers/Links.php
+++ b/application/api/controllers/Links.php
@@ -36,13 +36,6 @@ class Links extends ApiController
36 public function getLinks($request, $response) 36 public function getLinks($request, $response)
37 { 37 {
38 $private = $request->getParam('visibility'); 38 $private = $request->getParam('visibility');
39 $bookmarks = $this->bookmarkService->search(
40 [
41 'searchtags' => $request->getParam('searchtags', ''),
42 'searchterm' => $request->getParam('searchterm', ''),
43 ],
44 $private
45 );
46 39
47 // Return bookmarks from the {offset}th link, starting from 0. 40 // Return bookmarks from the {offset}th link, starting from 0.
48 $offset = $request->getParam('offset'); 41 $offset = $request->getParam('offset');
@@ -50,9 +43,6 @@ class Links extends ApiController
50 throw new ApiBadParametersException('Invalid offset'); 43 throw new ApiBadParametersException('Invalid offset');
51 } 44 }
52 $offset = ! empty($offset) ? intval($offset) : 0; 45 $offset = ! empty($offset) ? intval($offset) : 0;
53 if ($offset > count($bookmarks)) {
54 return $response->withJson([], 200, $this->jsonStyle);
55 }
56 46
57 // limit parameter is either a number of bookmarks or 'all' for everything. 47 // limit parameter is either a number of bookmarks or 'all' for everything.
58 $limit = $request->getParam('limit'); 48 $limit = $request->getParam('limit');
@@ -61,23 +51,33 @@ class Links extends ApiController
61 } elseif (ctype_digit($limit)) { 51 } elseif (ctype_digit($limit)) {
62 $limit = intval($limit); 52 $limit = intval($limit);
63 } elseif ($limit === 'all') { 53 } elseif ($limit === 'all') {
64 $limit = count($bookmarks); 54 $limit = null;
65 } else { 55 } else {
66 throw new ApiBadParametersException('Invalid limit'); 56 throw new ApiBadParametersException('Invalid limit');
67 } 57 }
68 58
59 $searchResult = $this->bookmarkService->search(
60 [
61 'searchtags' => $request->getParam('searchtags', ''),
62 'searchterm' => $request->getParam('searchterm', ''),
63 ],
64 $private,
65 false,
66 false,
67 false,
68 [
69 'limit' => $limit,
70 'offset' => $offset,
71 'allowOutOfBounds' => true,
72 ]
73 );
74
69 // 'environment' is set by Slim and encapsulate $_SERVER. 75 // 'environment' is set by Slim and encapsulate $_SERVER.
70 $indexUrl = index_url($this->ci['environment']); 76 $indexUrl = index_url($this->ci['environment']);
71 77
72 $out = []; 78 $out = [];
73 $index = 0; 79 foreach ($searchResult->getBookmarks() as $bookmark) {
74 foreach ($bookmarks as $bookmark) { 80 $out[] = ApiUtils::formatLink($bookmark, $indexUrl);
75 if (count($out) >= $limit) {
76 break;
77 }
78 if ($index++ >= $offset) {
79 $out[] = ApiUtils::formatLink($bookmark, $indexUrl);
80 }
81 } 81 }
82 82
83 return $response->withJson($out, 200, $this->jsonStyle); 83 return $response->withJson($out, 200, $this->jsonStyle);
diff --git a/application/api/controllers/Tags.php b/application/api/controllers/Tags.php
index e60e00a7..5a23f6db 100644
--- a/application/api/controllers/Tags.php
+++ b/application/api/controllers/Tags.php
@@ -122,12 +122,12 @@ class Tags extends ApiController
122 throw new ApiBadParametersException('New tag name is required in the request body'); 122 throw new ApiBadParametersException('New tag name is required in the request body');
123 } 123 }
124 124
125 $bookmarks = $this->bookmarkService->search( 125 $searchResult = $this->bookmarkService->search(
126 ['searchtags' => $args['tagName']], 126 ['searchtags' => $args['tagName']],
127 BookmarkFilter::$ALL, 127 BookmarkFilter::$ALL,
128 true 128 true
129 ); 129 );
130 foreach ($bookmarks as $bookmark) { 130 foreach ($searchResult->getBookmarks() as $bookmark) {
131 $bookmark->renameTag($args['tagName'], $data['name']); 131 $bookmark->renameTag($args['tagName'], $data['name']);
132 $this->bookmarkService->set($bookmark, false); 132 $this->bookmarkService->set($bookmark, false);
133 $this->history->updateLink($bookmark); 133 $this->history->updateLink($bookmark);
@@ -157,12 +157,12 @@ class Tags extends ApiController
157 throw new ApiTagNotFoundException(); 157 throw new ApiTagNotFoundException();
158 } 158 }
159 159
160 $bookmarks = $this->bookmarkService->search( 160 $searchResult = $this->bookmarkService->search(
161 ['searchtags' => $args['tagName']], 161 ['searchtags' => $args['tagName']],
162 BookmarkFilter::$ALL, 162 BookmarkFilter::$ALL,
163 true 163 true
164 ); 164 );
165 foreach ($bookmarks as $bookmark) { 165 foreach ($searchResult->getBookmarks() as $bookmark) {
166 $bookmark->deleteTag($args['tagName']); 166 $bookmark->deleteTag($args['tagName']);
167 $this->bookmarkService->set($bookmark, false); 167 $this->bookmarkService->set($bookmark, false);
168 $this->history->updateLink($bookmark); 168 $this->history->updateLink($bookmark);
diff --git a/application/bookmark/BookmarkFileService.php b/application/bookmark/BookmarkFileService.php
index 6666a251..8ea37427 100644
--- a/application/bookmark/BookmarkFileService.php
+++ b/application/bookmark/BookmarkFileService.php
@@ -55,8 +55,12 @@ class BookmarkFileService implements BookmarkServiceInterface
55 /** 55 /**
56 * @inheritDoc 56 * @inheritDoc
57 */ 57 */
58 public function __construct(ConfigManager $conf, History $history, Mutex $mutex, bool $isLoggedIn) 58 public function __construct(
59 { 59 ConfigManager $conf,
60 History $history,
61 Mutex $mutex,
62 bool $isLoggedIn
63 ) {
60 $this->conf = $conf; 64 $this->conf = $conf;
61 $this->history = $history; 65 $this->history = $history;
62 $this->mutex = $mutex; 66 $this->mutex = $mutex;
@@ -129,8 +133,9 @@ class BookmarkFileService implements BookmarkServiceInterface
129 string $visibility = null, 133 string $visibility = null,
130 bool $caseSensitive = false, 134 bool $caseSensitive = false,
131 bool $untaggedOnly = false, 135 bool $untaggedOnly = false,
132 bool $ignoreSticky = false 136 bool $ignoreSticky = false,
133 ) { 137 array $pagination = []
138 ): SearchResult {
134 if ($visibility === null) { 139 if ($visibility === null) {
135 $visibility = $this->isLoggedIn ? BookmarkFilter::$ALL : BookmarkFilter::$PUBLIC; 140 $visibility = $this->isLoggedIn ? BookmarkFilter::$ALL : BookmarkFilter::$PUBLIC;
136 } 141 }
@@ -143,13 +148,20 @@ class BookmarkFileService implements BookmarkServiceInterface
143 $this->bookmarks->reorder('DESC', true); 148 $this->bookmarks->reorder('DESC', true);
144 } 149 }
145 150
146 return $this->bookmarkFilter->filter( 151 $bookmarks = $this->bookmarkFilter->filter(
147 BookmarkFilter::$FILTER_TAG | BookmarkFilter::$FILTER_TEXT, 152 BookmarkFilter::$FILTER_TAG | BookmarkFilter::$FILTER_TEXT,
148 [$searchTags, $searchTerm], 153 [$searchTags, $searchTerm],
149 $caseSensitive, 154 $caseSensitive,
150 $visibility, 155 $visibility,
151 $untaggedOnly 156 $untaggedOnly
152 ); 157 );
158
159 return SearchResult::getSearchResult(
160 $bookmarks,
161 $pagination['offset'] ?? 0,
162 $pagination['limit'] ?? null,
163 $pagination['allowOutOfBounds'] ?? false
164 );
153 } 165 }
154 166
155 /** 167 /**
@@ -282,7 +294,7 @@ class BookmarkFileService implements BookmarkServiceInterface
282 */ 294 */
283 public function count(string $visibility = null): int 295 public function count(string $visibility = null): int
284 { 296 {
285 return count($this->search([], $visibility)); 297 return $this->search([], $visibility)->getResultCount();
286 } 298 }
287 299
288 /** 300 /**
@@ -305,10 +317,10 @@ class BookmarkFileService implements BookmarkServiceInterface
305 */ 317 */
306 public function bookmarksCountPerTag(array $filteringTags = [], string $visibility = null): array 318 public function bookmarksCountPerTag(array $filteringTags = [], string $visibility = null): array
307 { 319 {
308 $bookmarks = $this->search(['searchtags' => $filteringTags], $visibility); 320 $searchResult = $this->search(['searchtags' => $filteringTags], $visibility);
309 $tags = []; 321 $tags = [];
310 $caseMapping = []; 322 $caseMapping = [];
311 foreach ($bookmarks as $bookmark) { 323 foreach ($searchResult->getBookmarks() as $bookmark) {
312 foreach ($bookmark->getTags() as $tag) { 324 foreach ($bookmark->getTags() as $tag) {
313 if ( 325 if (
314 empty($tag) 326 empty($tag)
@@ -357,7 +369,7 @@ class BookmarkFileService implements BookmarkServiceInterface
357 $previous = null; 369 $previous = null;
358 $next = null; 370 $next = null;
359 371
360 foreach ($this->search([], null, false, false, true) as $bookmark) { 372 foreach ($this->search([], null, false, false, true)->getBookmarks() as $bookmark) {
361 if ($to < $bookmark->getCreated()) { 373 if ($to < $bookmark->getCreated()) {
362 $next = $bookmark->getCreated(); 374 $next = $bookmark->getCreated();
363 } elseif ($from < $bookmark->getCreated() && $to > $bookmark->getCreated()) { 375 } elseif ($from < $bookmark->getCreated() && $to > $bookmark->getCreated()) {
@@ -378,7 +390,7 @@ class BookmarkFileService implements BookmarkServiceInterface
378 */ 390 */
379 public function getLatest(): ?Bookmark 391 public function getLatest(): ?Bookmark
380 { 392 {
381 foreach ($this->search([], null, false, false, true) as $bookmark) { 393 foreach ($this->search([], null, false, false, true)->getBookmarks() as $bookmark) {
382 return $bookmark; 394 return $bookmark;
383 } 395 }
384 396
diff --git a/application/bookmark/BookmarkServiceInterface.php b/application/bookmark/BookmarkServiceInterface.php
index 08cdbb4e..4b1f0daa 100644
--- a/application/bookmark/BookmarkServiceInterface.php
+++ b/application/bookmark/BookmarkServiceInterface.php
@@ -44,16 +44,18 @@ interface BookmarkServiceInterface
44 * @param bool $caseSensitive 44 * @param bool $caseSensitive
45 * @param bool $untaggedOnly 45 * @param bool $untaggedOnly
46 * @param bool $ignoreSticky 46 * @param bool $ignoreSticky
47 * @param array $pagination This array can contain the following keys for pagination: limit, offset.
47 * 48 *
48 * @return Bookmark[] 49 * @return SearchResult
49 */ 50 */
50 public function search( 51 public function search(
51 array $request = [], 52 array $request = [],
52 string $visibility = null, 53 string $visibility = null,
53 bool $caseSensitive = false, 54 bool $caseSensitive = false,
54 bool $untaggedOnly = false, 55 bool $untaggedOnly = false,
55 bool $ignoreSticky = false 56 bool $ignoreSticky = false,
56 ); 57 array $pagination = []
58 ): SearchResult;
57 59
58 /** 60 /**
59 * Get a single bookmark by its ID. 61 * Get a single bookmark by its ID.
diff --git a/application/bookmark/SearchResult.php b/application/bookmark/SearchResult.php
new file mode 100644
index 00000000..c0bce311
--- /dev/null
+++ b/application/bookmark/SearchResult.php
@@ -0,0 +1,136 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Bookmark;
6
7/**
8 * Read-only class used to represent search result, including pagination.
9 */
10class SearchResult
11{
12 /** @var Bookmark[] List of result bookmarks with pagination applied */
13 protected $bookmarks;
14
15 /** @var int number of Bookmarks found, with pagination applied */
16 protected $resultCount;
17
18 /** @var int total number of result found */
19 protected $totalCount;
20
21 /** @var int pagination: limit number of result bookmarks */
22 protected $limit;
23
24 /** @var int pagination: offset to apply to complete result list */
25 protected $offset;
26
27 public function __construct(array $bookmarks, int $totalCount, int $offset, ?int $limit)
28 {
29 $this->bookmarks = $bookmarks;
30 $this->resultCount = count($bookmarks);
31 $this->totalCount = $totalCount;
32 $this->limit = $limit;
33 $this->offset = $offset;
34 }
35
36 /**
37 * Build a SearchResult from provided full result set and pagination settings.
38 *
39 * @param Bookmark[] $bookmarks Full set of result which will be filtered
40 * @param int $offset Start recording results from $offset
41 * @param int|null $limit End recording results after $limit bookmarks is reached
42 * @param bool $allowOutOfBounds Set to false to display the last page if the offset is out of bound,
43 * return empty result set otherwise (default: false)
44 *
45 * @return SearchResult
46 */
47 public static function getSearchResult(
48 $bookmarks,
49 int $offset = 0,
50 ?int $limit = null,
51 bool $allowOutOfBounds = false
52 ): self {
53 $totalCount = count($bookmarks);
54 if (!$allowOutOfBounds && $offset > $totalCount) {
55 $offset = $limit === null ? 0 : $limit * -1;
56 }
57
58 if ($bookmarks instanceof BookmarkArray) {
59 $buffer = [];
60 foreach ($bookmarks as $key => $value) {
61 $buffer[$key] = $value;
62 }
63 $bookmarks = $buffer;
64 }
65
66 return new static(
67 array_slice($bookmarks, $offset, $limit, true),
68 $totalCount,
69 $offset,
70 $limit
71 );
72 }
73
74 /** @return Bookmark[] List of result bookmarks with pagination applied */
75 public function getBookmarks(): array
76 {
77 return $this->bookmarks;
78 }
79
80 /** @return int number of Bookmarks found, with pagination applied */
81 public function getResultCount(): int
82 {
83 return $this->resultCount;
84 }
85
86 /** @return int total number of result found */
87 public function getTotalCount(): int
88 {
89 return $this->totalCount;
90 }
91
92 /** @return int pagination: limit number of result bookmarks */
93 public function getLimit(): ?int
94 {
95 return $this->limit;
96 }
97
98 /** @return int pagination: offset to apply to complete result list */
99 public function getOffset(): int
100 {
101 return $this->offset;
102 }
103
104 /** @return int Current page of result set in complete results */
105 public function getPage(): int
106 {
107 if (empty($this->limit)) {
108 return $this->offset === 0 ? 1 : 2;
109 }
110 $base = $this->offset >= 0 ? $this->offset : $this->totalCount + $this->offset;
111
112 return (int) ceil($base / $this->limit) + 1;
113 }
114
115 /** @return int Get the # of the last page */
116 public function getLastPage(): int
117 {
118 if (empty($this->limit)) {
119 return $this->offset === 0 ? 1 : 2;
120 }
121
122 return (int) ceil($this->totalCount / $this->limit);
123 }
124
125 /** @return bool Either the current page is the last one or not */
126 public function isLastPage(): bool
127 {
128 return $this->getPage() === $this->getLastPage();
129 }
130
131 /** @return bool Either the current page is the first one or not */
132 public function isFirstPage(): bool
133 {
134 return $this->offset === 0;
135 }
136}
diff --git a/application/feed/FeedBuilder.php b/application/feed/FeedBuilder.php
index ed62af26..d5d74fd1 100644
--- a/application/feed/FeedBuilder.php
+++ b/application/feed/FeedBuilder.php
@@ -102,22 +102,16 @@ class FeedBuilder
102 $userInput['searchtags'] = false; 102 $userInput['searchtags'] = false;
103 } 103 }
104 104
105 // Optionally filter the results: 105 $limit = $this->getLimit($userInput);
106 $linksToDisplay = $this->linkDB->search($userInput ?? [], null, false, false, true);
107
108 $nblinksToDisplay = $this->getNbLinks(count($linksToDisplay), $userInput);
109 106
110 // Can't use array_keys() because $link is a LinkDB instance and not a real array. 107 // Optionally filter the results:
111 $keys = []; 108 $searchResult = $this->linkDB->search($userInput ?? [], null, false, false, true, ['limit' => $limit]);
112 foreach ($linksToDisplay as $key => $value) {
113 $keys[] = $key;
114 }
115 109
116 $pageaddr = escape(index_url($this->serverInfo)); 110 $pageaddr = escape(index_url($this->serverInfo));
117 $this->formatter->addContextData('index_url', $pageaddr); 111 $this->formatter->addContextData('index_url', $pageaddr);
118 $linkDisplayed = []; 112 $links = [];
119 for ($i = 0; $i < $nblinksToDisplay && $i < count($keys); $i++) { 113 foreach ($searchResult->getBookmarks() as $key => $bookmark) {
120 $linkDisplayed[$keys[$i]] = $this->buildItem($feedType, $linksToDisplay[$keys[$i]], $pageaddr); 114 $links[$key] = $this->buildItem($feedType, $bookmark, $pageaddr);
121 } 115 }
122 116
123 $data['language'] = $this->getTypeLanguage($feedType); 117 $data['language'] = $this->getTypeLanguage($feedType);
@@ -128,7 +122,7 @@ class FeedBuilder
128 $data['self_link'] = $pageaddr . $requestUri; 122 $data['self_link'] = $pageaddr . $requestUri;
129 $data['index_url'] = $pageaddr; 123 $data['index_url'] = $pageaddr;
130 $data['usepermalinks'] = $this->usePermalinks === true; 124 $data['usepermalinks'] = $this->usePermalinks === true;
131 $data['links'] = $linkDisplayed; 125 $data['links'] = $links;
132 126
133 return $data; 127 return $data;
134 } 128 }
@@ -268,19 +262,18 @@ class FeedBuilder
268 * If 'nb' not set or invalid, default value: $DEFAULT_NB_LINKS. 262 * If 'nb' not set or invalid, default value: $DEFAULT_NB_LINKS.
269 * If 'nb' is set to 'all', display all filtered bookmarks (max parameter). 263 * If 'nb' is set to 'all', display all filtered bookmarks (max parameter).
270 * 264 *
271 * @param int $max maximum number of bookmarks to display.
272 * @param array $userInput $_GET. 265 * @param array $userInput $_GET.
273 * 266 *
274 * @return int number of bookmarks to display. 267 * @return int number of bookmarks to display.
275 */ 268 */
276 protected function getNbLinks($max, ?array $userInput) 269 protected function getLimit(?array $userInput)
277 { 270 {
278 if (empty($userInput['nb'])) { 271 if (empty($userInput['nb'])) {
279 return self::$DEFAULT_NB_LINKS; 272 return self::$DEFAULT_NB_LINKS;
280 } 273 }
281 274
282 if ($userInput['nb'] == 'all') { 275 if ($userInput['nb'] == 'all') {
283 return $max; 276 return null;
284 } 277 }
285 278
286 $intNb = intval($userInput['nb']); 279 $intNb = intval($userInput['nb']);
diff --git a/application/front/controller/admin/ManageTagController.php b/application/front/controller/admin/ManageTagController.php
index 8675a0c5..1333cce7 100644
--- a/application/front/controller/admin/ManageTagController.php
+++ b/application/front/controller/admin/ManageTagController.php
@@ -57,9 +57,12 @@ class ManageTagController extends ShaarliAdminController
57 } 57 }
58 58
59 // TODO: move this to bookmark service 59 // TODO: move this to bookmark service
60 $count = 0; 60 $searchResult = $this->container->bookmarkService->search(
61 $bookmarks = $this->container->bookmarkService->search(['searchtags' => $fromTag], BookmarkFilter::$ALL, true); 61 ['searchtags' => $fromTag],
62 foreach ($bookmarks as $bookmark) { 62 BookmarkFilter::$ALL,
63 true
64 );
65 foreach ($searchResult->getBookmarks() as $bookmark) {
63 if (false === $isDelete) { 66 if (false === $isDelete) {
64 $bookmark->renameTag($fromTag, $toTag); 67 $bookmark->renameTag($fromTag, $toTag);
65 } else { 68 } else {
@@ -68,11 +71,11 @@ class ManageTagController extends ShaarliAdminController
68 71
69 $this->container->bookmarkService->set($bookmark, false); 72 $this->container->bookmarkService->set($bookmark, false);
70 $this->container->history->updateLink($bookmark); 73 $this->container->history->updateLink($bookmark);
71 $count++;
72 } 74 }
73 75
74 $this->container->bookmarkService->save(); 76 $this->container->bookmarkService->save();
75 77
78 $count = $searchResult->getResultCount();
76 if (true === $isDelete) { 79 if (true === $isDelete) {
77 $alert = sprintf( 80 $alert = sprintf(
78 t('The tag was removed from %d bookmark.', 'The tag was removed from %d bookmarks.', $count), 81 t('The tag was removed from %d bookmark.', 'The tag was removed from %d bookmarks.', $count),
diff --git a/application/front/controller/admin/ThumbnailsController.php b/application/front/controller/admin/ThumbnailsController.php
index 94d97d4b..5dfea096 100644
--- a/application/front/controller/admin/ThumbnailsController.php
+++ b/application/front/controller/admin/ThumbnailsController.php
@@ -22,7 +22,7 @@ class ThumbnailsController extends ShaarliAdminController
22 public function index(Request $request, Response $response): Response 22 public function index(Request $request, Response $response): Response
23 { 23 {
24 $ids = []; 24 $ids = [];
25 foreach ($this->container->bookmarkService->search() as $bookmark) { 25 foreach ($this->container->bookmarkService->search()->getBookmarks() as $bookmark) {
26 // A note or not HTTP(S) 26 // A note or not HTTP(S)
27 if ($bookmark->isNote() || !startsWith(strtolower($bookmark->getUrl()), 'http')) { 27 if ($bookmark->isNote() || !startsWith(strtolower($bookmark->getUrl()), 'http')) {
28 continue; 28 continue;
diff --git a/application/front/controller/visitor/BookmarkListController.php b/application/front/controller/visitor/BookmarkListController.php
index fe8231be..321ca813 100644
--- a/application/front/controller/visitor/BookmarkListController.php
+++ b/application/front/controller/visitor/BookmarkListController.php
@@ -36,7 +36,6 @@ class BookmarkListController extends ShaarliVisitorController
36 36
37 $searchTags = normalize_spaces($request->getParam('searchtags') ?? ''); 37 $searchTags = normalize_spaces($request->getParam('searchtags') ?? '');
38 $searchTerm = escape(normalize_spaces($request->getParam('searchterm') ?? '')); 38 $searchTerm = escape(normalize_spaces($request->getParam('searchterm') ?? ''));
39 ;
40 39
41 // Filter bookmarks according search parameters. 40 // Filter bookmarks according search parameters.
42 $visibility = $this->container->sessionManager->getSessionParameter('visibility'); 41 $visibility = $this->container->sessionManager->getSessionParameter('visibility');
@@ -44,39 +43,26 @@ class BookmarkListController extends ShaarliVisitorController
44 'searchtags' => $searchTags, 43 'searchtags' => $searchTags,
45 'searchterm' => $searchTerm, 44 'searchterm' => $searchTerm,
46 ]; 45 ];
47 $linksToDisplay = $this->container->bookmarkService->search(
48 $search,
49 $visibility,
50 false,
51 !!$this->container->sessionManager->getSessionParameter('untaggedonly')
52 ) ?? [];
53
54 // ---- Handle paging.
55 $keys = [];
56 foreach ($linksToDisplay as $key => $value) {
57 $keys[] = $key;
58 }
59
60 $linksPerPage = $this->container->sessionManager->getSessionParameter('LINKS_PER_PAGE', 20) ?: 20;
61 46
62 // Select articles according to paging. 47 // Select articles according to paging.
63 $pageCount = (int) ceil(count($keys) / $linksPerPage) ?: 1; 48 $page = (int) ($request->getParam('page') ?? 1);
64 $page = (int) $request->getParam('page') ?? 1;
65 $page = $page < 1 ? 1 : $page; 49 $page = $page < 1 ? 1 : $page;
66 $page = $page > $pageCount ? $pageCount : $page; 50 $linksPerPage = $this->container->sessionManager->getSessionParameter('LINKS_PER_PAGE', 20) ?: 20;
67 51
68 // Start index. 52 $searchResult = $this->container->bookmarkService->search(
69 $i = ($page - 1) * $linksPerPage; 53 $search,
70 $end = $i + $linksPerPage; 54 $visibility,
55 false,
56 !!$this->container->sessionManager->getSessionParameter('untaggedonly'),
57 false,
58 ['offset' => $linksPerPage * ($page - 1), 'limit' => $linksPerPage]
59 ) ?? [];
71 60
72 $linkDisp = [];
73 $save = false; 61 $save = false;
74 while ($i < $end && $i < count($keys)) { 62 $links = [];
75 $save = $this->updateThumbnail($linksToDisplay[$keys[$i]], false) || $save; 63 foreach ($searchResult->getBookmarks() as $key => $bookmark) {
76 $link = $formatter->format($linksToDisplay[$keys[$i]]); 64 $save = $this->updateThumbnail($bookmark, false) || $save;
77 65 $links[$key] = $formatter->format($bookmark);
78 $linkDisp[$keys[$i]] = $link;
79 $i++;
80 } 66 }
81 67
82 if ($save) { 68 if ($save) {
@@ -86,15 +72,10 @@ class BookmarkListController extends ShaarliVisitorController
86 // Compute paging navigation 72 // Compute paging navigation
87 $searchtagsUrl = $searchTags === '' ? '' : '&searchtags=' . urlencode($searchTags); 73 $searchtagsUrl = $searchTags === '' ? '' : '&searchtags=' . urlencode($searchTags);
88 $searchtermUrl = $searchTerm === '' ? '' : '&searchterm=' . urlencode($searchTerm); 74 $searchtermUrl = $searchTerm === '' ? '' : '&searchterm=' . urlencode($searchTerm);
75 $page = $searchResult->getPage();
89 76
90 $previous_page_url = ''; 77 $previousPageUrl = !$searchResult->isLastPage() ? '?page=' . ($page + 1) . $searchtermUrl . $searchtagsUrl : '';
91 if ($i !== count($keys)) { 78 $nextPageUrl = !$searchResult->isFirstPage() ? '?page=' . ($page - 1) . $searchtermUrl . $searchtagsUrl : '';
92 $previous_page_url = '?page=' . ($page + 1) . $searchtermUrl . $searchtagsUrl;
93 }
94 $next_page_url = '';
95 if ($page > 1) {
96 $next_page_url = '?page=' . ($page - 1) . $searchtermUrl . $searchtagsUrl;
97 }
98 79
99 $tagsSeparator = $this->container->conf->get('general.tags_separator', ' '); 80 $tagsSeparator = $this->container->conf->get('general.tags_separator', ' ');
100 $searchTagsUrlEncoded = array_map('urlencode', tags_str2array($searchTags, $tagsSeparator)); 81 $searchTagsUrlEncoded = array_map('urlencode', tags_str2array($searchTags, $tagsSeparator));
@@ -104,16 +85,16 @@ class BookmarkListController extends ShaarliVisitorController
104 $data = array_merge( 85 $data = array_merge(
105 $this->initializeTemplateVars(), 86 $this->initializeTemplateVars(),
106 [ 87 [
107 'previous_page_url' => $previous_page_url, 88 'previous_page_url' => $previousPageUrl,
108 'next_page_url' => $next_page_url, 89 'next_page_url' => $nextPageUrl,
109 'page_current' => $page, 90 'page_current' => $page,
110 'page_max' => $pageCount, 91 'page_max' => $searchResult->getLastPage(),
111 'result_count' => count($linksToDisplay), 92 'result_count' => $searchResult->getTotalCount(),
112 'search_term' => escape($searchTerm), 93 'search_term' => escape($searchTerm),
113 'search_tags' => escape($searchTags), 94 'search_tags' => escape($searchTags),
114 'search_tags_url' => $searchTagsUrlEncoded, 95 'search_tags_url' => $searchTagsUrlEncoded,
115 'visibility' => $visibility, 96 'visibility' => $visibility,
116 'links' => $linkDisp, 97 'links' => $links,
117 ] 98 ]
118 ); 99 );
119 100
diff --git a/application/front/controller/visitor/DailyController.php b/application/front/controller/visitor/DailyController.php
index 29492a5f..3739ec16 100644
--- a/application/front/controller/visitor/DailyController.php
+++ b/application/front/controller/visitor/DailyController.php
@@ -100,7 +100,7 @@ class DailyController extends ShaarliVisitorController
100 $days = []; 100 $days = [];
101 $format = DailyPageHelper::getFormatByType($type); 101 $format = DailyPageHelper::getFormatByType($type);
102 $length = DailyPageHelper::getRssLengthByType($type); 102 $length = DailyPageHelper::getRssLengthByType($type);
103 foreach ($this->container->bookmarkService->search() as $bookmark) { 103 foreach ($this->container->bookmarkService->search()->getBookmarks() as $bookmark) {
104 $day = $bookmark->getCreated()->format($format); 104 $day = $bookmark->getCreated()->format($format);
105 105
106 // Stop iterating after DAILY_RSS_NB_DAYS entries 106 // Stop iterating after DAILY_RSS_NB_DAYS entries
diff --git a/application/front/controller/visitor/PictureWallController.php b/application/front/controller/visitor/PictureWallController.php
index 23553ee6..9c8f07d7 100644
--- a/application/front/controller/visitor/PictureWallController.php
+++ b/application/front/controller/visitor/PictureWallController.php
@@ -30,19 +30,19 @@ class PictureWallController extends ShaarliVisitorController
30 ); 30 );
31 31
32 // Optionally filter the results: 32 // Optionally filter the results:
33 $links = $this->container->bookmarkService->search($request->getQueryParams()); 33 $bookmarks = $this->container->bookmarkService->search($request->getQueryParams())->getBookmarks();
34 $linksToDisplay = []; 34 $links = [];
35 35
36 // Get only bookmarks which have a thumbnail. 36 // Get only bookmarks which have a thumbnail.
37 // Note: we do not retrieve thumbnails here, the request is too heavy. 37 // Note: we do not retrieve thumbnails here, the request is too heavy.
38 $formatter = $this->container->formatterFactory->getFormatter('raw'); 38 $formatter = $this->container->formatterFactory->getFormatter('raw');
39 foreach ($links as $key => $link) { 39 foreach ($bookmarks as $key => $bookmark) {
40 if (!empty($link->getThumbnail())) { 40 if (!empty($bookmark->getThumbnail())) {
41 $linksToDisplay[] = $formatter->format($link); 41 $links[] = $formatter->format($bookmark);
42 } 42 }
43 } 43 }
44 44
45 $data = ['linksToDisplay' => $linksToDisplay]; 45 $data = ['linksToDisplay' => $links];
46 $this->executePageHooks('render_picwall', $data, TemplatePage::PICTURE_WALL); 46 $this->executePageHooks('render_picwall', $data, TemplatePage::PICTURE_WALL);
47 47
48 foreach ($data as $key => $value) { 48 foreach ($data as $key => $value) {
diff --git a/application/netscape/NetscapeBookmarkUtils.php b/application/netscape/NetscapeBookmarkUtils.php
index 2d97b4c8..20715bd0 100644
--- a/application/netscape/NetscapeBookmarkUtils.php
+++ b/application/netscape/NetscapeBookmarkUtils.php
@@ -64,7 +64,7 @@ class NetscapeBookmarkUtils
64 } 64 }
65 65
66 $bookmarkLinks = []; 66 $bookmarkLinks = [];
67 foreach ($this->bookmarkService->search([], $selection) as $bookmark) { 67 foreach ($this->bookmarkService->search([], $selection)->getBookmarks() as $bookmark) {
68 $link = $formatter->format($bookmark); 68 $link = $formatter->format($bookmark);
69 $link['taglist'] = implode(',', $bookmark->getTags()); 69 $link['taglist'] = implode(',', $bookmark->getTags());
70 if ($bookmark->isNote() && $prependNoteUrl) { 70 if ($bookmark->isNote() && $prependNoteUrl) {
diff --git a/application/updater/Updater.php b/application/updater/Updater.php
index 4f557d0f..11b6c051 100644
--- a/application/updater/Updater.php
+++ b/application/updater/Updater.php
@@ -152,7 +152,7 @@ class Updater
152 { 152 {
153 $updated = false; 153 $updated = false;
154 154
155 foreach ($this->bookmarkService->search() as $bookmark) { 155 foreach ($this->bookmarkService->search()->getBookmarks() as $bookmark) {
156 if ( 156 if (
157 $bookmark->isNote() 157 $bookmark->isNote()
158 && startsWith($bookmark->getUrl(), '?') 158 && startsWith($bookmark->getUrl(), '?')
diff --git a/tests/bookmark/BookmarkFileServiceTest.php b/tests/bookmark/BookmarkFileServiceTest.php
index f619aff3..d1af3fb0 100644
--- a/tests/bookmark/BookmarkFileServiceTest.php
+++ b/tests/bookmark/BookmarkFileServiceTest.php
@@ -807,7 +807,7 @@ class BookmarkFileServiceTest extends TestCase
807 $request = ['searchtags' => $tags]; 807 $request = ['searchtags' => $tags];
808 $this->assertEquals( 808 $this->assertEquals(
809 2, 809 2,
810 count($this->privateLinkDB->search($request, null, true)) 810 count($this->privateLinkDB->search($request, null, true)->getBookmarks())
811 ); 811 );
812 } 812 }
813 813
@@ -820,7 +820,7 @@ class BookmarkFileServiceTest extends TestCase
820 $request = ['searchtags' => $tags]; 820 $request = ['searchtags' => $tags];
821 $this->assertEquals( 821 $this->assertEquals(
822 2, 822 2,
823 count($this->privateLinkDB->search($request, null, true)) 823 count($this->privateLinkDB->search($request, null, true)->getBookmarks())
824 ); 824 );
825 } 825 }
826 826
@@ -834,12 +834,12 @@ class BookmarkFileServiceTest extends TestCase
834 $request = ['searchtags' => $tags]; 834 $request = ['searchtags' => $tags];
835 $this->assertEquals( 835 $this->assertEquals(
836 1, 836 1,
837 count($this->privateLinkDB->search($request, 'all', true)) 837 count($this->privateLinkDB->search($request, 'all', true)->getBookmarks())
838 ); 838 );
839 839
840 $this->assertEquals( 840 $this->assertEquals(
841 0, 841 0,
842 count($this->publicLinkDB->search($request, 'public', true)) 842 count($this->publicLinkDB->search($request, 'public', true)->getBookmarks())
843 ); 843 );
844 } 844 }
845 845
diff --git a/tests/bookmark/SearchResultTest.php b/tests/bookmark/SearchResultTest.php
new file mode 100644
index 00000000..12854c1f
--- /dev/null
+++ b/tests/bookmark/SearchResultTest.php
@@ -0,0 +1,125 @@
1<?php
2
3declare(strict_types=1);
4
5namespace Shaarli\Bookmark;
6
7use Shaarli\TestCase;
8
9/**
10 * Test SearchResult class.
11 */
12class SearchResultTest extends TestCase
13{
14 /** Create a SearchResult without any pagination parameter. */
15 public function testResultNoParameters(): void
16 {
17 $searchResult = SearchResult::getSearchResult($data = ['a', 'b', 'c', 'd', 'e', 'f']);
18
19 static::assertSame($data, $searchResult->getBookmarks());
20 static::assertSame(6, $searchResult->getResultCount());
21 static::assertSame(6, $searchResult->getTotalCount());
22 static::assertSame(null, $searchResult->getLimit());
23 static::assertSame(0, $searchResult->getOffset());
24 static::assertSame(1, $searchResult->getPage());
25 static::assertSame(1, $searchResult->getLastPage());
26 static::assertTrue($searchResult->isFirstPage());
27 static::assertTrue($searchResult->isLastPage());
28 }
29
30 /** Create a SearchResult with only an offset parameter */
31 public function testResultWithOffset(): void
32 {
33 $searchResult = SearchResult::getSearchResult(['a', 'b', 'c', 'd', 'e', 'f'], 2);
34
35 static::assertSame([2 => 'c', 3 => 'd', 4 => 'e', 5 => 'f'], $searchResult->getBookmarks());
36 static::assertSame(4, $searchResult->getResultCount());
37 static::assertSame(6, $searchResult->getTotalCount());
38 static::assertSame(null, $searchResult->getLimit());
39 static::assertSame(2, $searchResult->getOffset());
40 static::assertSame(2, $searchResult->getPage());
41 static::assertSame(2, $searchResult->getLastPage());
42 static::assertFalse($searchResult->isFirstPage());
43 static::assertTrue($searchResult->isLastPage());
44 }
45
46 /** Create a SearchResult with only a limit parameter */
47 public function testResultWithLimit(): void
48 {
49 $searchResult = SearchResult::getSearchResult(['a', 'b', 'c', 'd', 'e', 'f'], 0, 2);
50
51 static::assertSame([0 => 'a', 1 => 'b'], $searchResult->getBookmarks());
52 static::assertSame(2, $searchResult->getResultCount());
53 static::assertSame(6, $searchResult->getTotalCount());
54 static::assertSame(2, $searchResult->getLimit());
55 static::assertSame(0, $searchResult->getOffset());
56 static::assertSame(1, $searchResult->getPage());
57 static::assertSame(3, $searchResult->getLastPage());
58 static::assertTrue($searchResult->isFirstPage());
59 static::assertFalse($searchResult->isLastPage());
60 }
61
62 /** Create a SearchResult with offset and limit parameters */
63 public function testResultWithLimitAndOffset(): void
64 {
65 $searchResult = SearchResult::getSearchResult(['a', 'b', 'c', 'd', 'e', 'f'], 2, 2);
66
67 static::assertSame([2 => 'c', 3 => 'd'], $searchResult->getBookmarks());
68 static::assertSame(2, $searchResult->getResultCount());
69 static::assertSame(6, $searchResult->getTotalCount());
70 static::assertSame(2, $searchResult->getLimit());
71 static::assertSame(2, $searchResult->getOffset());
72 static::assertSame(2, $searchResult->getPage());
73 static::assertSame(3, $searchResult->getLastPage());
74 static::assertFalse($searchResult->isFirstPage());
75 static::assertFalse($searchResult->isLastPage());
76 }
77
78 /** Create a SearchResult with offset and limit parameters displaying the last page */
79 public function testResultWithLimitAndOffsetLastPage(): void
80 {
81 $searchResult = SearchResult::getSearchResult(['a', 'b', 'c', 'd', 'e', 'f'], 4, 2);
82
83 static::assertSame([4 => 'e', 5 => 'f'], $searchResult->getBookmarks());
84 static::assertSame(2, $searchResult->getResultCount());
85 static::assertSame(6, $searchResult->getTotalCount());
86 static::assertSame(2, $searchResult->getLimit());
87 static::assertSame(4, $searchResult->getOffset());
88 static::assertSame(3, $searchResult->getPage());
89 static::assertSame(3, $searchResult->getLastPage());
90 static::assertFalse($searchResult->isFirstPage());
91 static::assertTrue($searchResult->isLastPage());
92 }
93
94 /** Create a SearchResult with offset and limit parameters out of bound (display the last page) */
95 public function testResultWithLimitAndOffsetOutOfBounds(): void
96 {
97 $searchResult = SearchResult::getSearchResult(['a', 'b', 'c', 'd', 'e', 'f'], 12, 2);
98
99 static::assertSame([4 => 'e', 5 => 'f'], $searchResult->getBookmarks());
100 static::assertSame(2, $searchResult->getResultCount());
101 static::assertSame(6, $searchResult->getTotalCount());
102 static::assertSame(2, $searchResult->getLimit());
103 static::assertSame(-2, $searchResult->getOffset());
104 static::assertSame(3, $searchResult->getPage());
105 static::assertSame(3, $searchResult->getLastPage());
106 static::assertFalse($searchResult->isFirstPage());
107 static::assertTrue($searchResult->isLastPage());
108 }
109
110 /** Create a SearchResult with offset and limit parameters out of bound (no result) */
111 public function testResultWithLimitAndOffsetOutOfBoundsNoResult(): void
112 {
113 $searchResult = SearchResult::getSearchResult(['a', 'b', 'c', 'd', 'e', 'f'], 12, 2, true);
114
115 static::assertSame([], $searchResult->getBookmarks());
116 static::assertSame(0, $searchResult->getResultCount());
117 static::assertSame(6, $searchResult->getTotalCount());
118 static::assertSame(2, $searchResult->getLimit());
119 static::assertSame(12, $searchResult->getOffset());
120 static::assertSame(7, $searchResult->getPage());
121 static::assertSame(3, $searchResult->getLastPage());
122 static::assertFalse($searchResult->isFirstPage());
123 static::assertFalse($searchResult->isLastPage());
124 }
125}
diff --git a/tests/front/controller/admin/ManageTagControllerTest.php b/tests/front/controller/admin/ManageTagControllerTest.php
index af6f273f..56a64cbb 100644
--- a/tests/front/controller/admin/ManageTagControllerTest.php
+++ b/tests/front/controller/admin/ManageTagControllerTest.php
@@ -6,6 +6,7 @@ namespace Shaarli\Front\Controller\Admin;
6 6
7use Shaarli\Bookmark\Bookmark; 7use Shaarli\Bookmark\Bookmark;
8use Shaarli\Bookmark\BookmarkFilter; 8use Shaarli\Bookmark\BookmarkFilter;
9use Shaarli\Bookmark\SearchResult;
9use Shaarli\Config\ConfigManager; 10use Shaarli\Config\ConfigManager;
10use Shaarli\Front\Exception\WrongTokenException; 11use Shaarli\Front\Exception\WrongTokenException;
11use Shaarli\Security\SessionManager; 12use Shaarli\Security\SessionManager;
@@ -100,11 +101,11 @@ class ManageTagControllerTest extends TestCase
100 ->expects(static::once()) 101 ->expects(static::once())
101 ->method('search') 102 ->method('search')
102 ->with(['searchtags' => 'old-tag'], BookmarkFilter::$ALL, true) 103 ->with(['searchtags' => 'old-tag'], BookmarkFilter::$ALL, true)
103 ->willReturnCallback(function () use ($bookmark1, $bookmark2): array { 104 ->willReturnCallback(function () use ($bookmark1, $bookmark2): SearchResult {
104 $bookmark1->expects(static::once())->method('renameTag')->with('old-tag', 'new-tag'); 105 $bookmark1->expects(static::once())->method('renameTag')->with('old-tag', 'new-tag');
105 $bookmark2->expects(static::once())->method('renameTag')->with('old-tag', 'new-tag'); 106 $bookmark2->expects(static::once())->method('renameTag')->with('old-tag', 'new-tag');
106 107
107 return [$bookmark1, $bookmark2]; 108 return SearchResult::getSearchResult([$bookmark1, $bookmark2]);
108 }) 109 })
109 ; 110 ;
110 $this->container->bookmarkService 111 $this->container->bookmarkService
@@ -153,11 +154,11 @@ class ManageTagControllerTest extends TestCase
153 ->expects(static::once()) 154 ->expects(static::once())
154 ->method('search') 155 ->method('search')
155 ->with(['searchtags' => 'old-tag'], BookmarkFilter::$ALL, true) 156 ->with(['searchtags' => 'old-tag'], BookmarkFilter::$ALL, true)
156 ->willReturnCallback(function () use ($bookmark1, $bookmark2): array { 157 ->willReturnCallback(function () use ($bookmark1, $bookmark2): SearchResult {
157 $bookmark1->expects(static::once())->method('deleteTag')->with('old-tag'); 158 $bookmark1->expects(static::once())->method('deleteTag')->with('old-tag');
158 $bookmark2->expects(static::once())->method('deleteTag')->with('old-tag'); 159 $bookmark2->expects(static::once())->method('deleteTag')->with('old-tag');
159 160
160 return [$bookmark1, $bookmark2]; 161 return SearchResult::getSearchResult([$bookmark1, $bookmark2]);
161 }) 162 })
162 ; 163 ;
163 $this->container->bookmarkService 164 $this->container->bookmarkService
diff --git a/tests/front/controller/admin/ThumbnailsControllerTest.php b/tests/front/controller/admin/ThumbnailsControllerTest.php
index e5749654..0c9b63c3 100644
--- a/tests/front/controller/admin/ThumbnailsControllerTest.php
+++ b/tests/front/controller/admin/ThumbnailsControllerTest.php
@@ -6,6 +6,7 @@ namespace Shaarli\Front\Controller\Admin;
6 6
7use Shaarli\Bookmark\Bookmark; 7use Shaarli\Bookmark\Bookmark;
8use Shaarli\Bookmark\Exception\BookmarkNotFoundException; 8use Shaarli\Bookmark\Exception\BookmarkNotFoundException;
9use Shaarli\Bookmark\SearchResult;
9use Shaarli\TestCase; 10use Shaarli\TestCase;
10use Shaarli\Thumbnailer; 11use Shaarli\Thumbnailer;
11use Slim\Http\Request; 12use Slim\Http\Request;
@@ -40,12 +41,12 @@ class ThumbnailsControllerTest extends TestCase
40 $this->container->bookmarkService 41 $this->container->bookmarkService
41 ->expects(static::once()) 42 ->expects(static::once())
42 ->method('search') 43 ->method('search')
43 ->willReturn([ 44 ->willReturn(SearchResult::getSearchResult([
44 (new Bookmark())->setId(1)->setUrl('http://url1.tld')->setTitle('Title 1'), 45 (new Bookmark())->setId(1)->setUrl('http://url1.tld')->setTitle('Title 1'),
45 (new Bookmark())->setId(2)->setUrl('?abcdef')->setTitle('Note 1'), 46 (new Bookmark())->setId(2)->setUrl('?abcdef')->setTitle('Note 1'),
46 (new Bookmark())->setId(3)->setUrl('http://url2.tld')->setTitle('Title 2'), 47 (new Bookmark())->setId(3)->setUrl('http://url2.tld')->setTitle('Title 2'),
47 (new Bookmark())->setId(4)->setUrl('ftp://domain.tld', ['ftp'])->setTitle('FTP'), 48 (new Bookmark())->setId(4)->setUrl('ftp://domain.tld', ['ftp'])->setTitle('FTP'),
48 ]) 49 ]))
49 ; 50 ;
50 51
51 $result = $this->controller->index($request, $response); 52 $result = $this->controller->index($request, $response);
diff --git a/tests/front/controller/visitor/BookmarkListControllerTest.php b/tests/front/controller/visitor/BookmarkListControllerTest.php
index dec938f2..0fbab9d4 100644
--- a/tests/front/controller/visitor/BookmarkListControllerTest.php
+++ b/tests/front/controller/visitor/BookmarkListControllerTest.php
@@ -6,6 +6,7 @@ namespace Shaarli\Front\Controller\Visitor;
6 6
7use Shaarli\Bookmark\Bookmark; 7use Shaarli\Bookmark\Bookmark;
8use Shaarli\Bookmark\Exception\BookmarkNotFoundException; 8use Shaarli\Bookmark\Exception\BookmarkNotFoundException;
9use Shaarli\Bookmark\SearchResult;
9use Shaarli\Config\ConfigManager; 10use Shaarli\Config\ConfigManager;
10use Shaarli\Security\LoginManager; 11use Shaarli\Security\LoginManager;
11use Shaarli\TestCase; 12use Shaarli\TestCase;
@@ -45,13 +46,15 @@ class BookmarkListControllerTest extends TestCase
45 ['searchtags' => '', 'searchterm' => ''], 46 ['searchtags' => '', 'searchterm' => ''],
46 null, 47 null,
47 false, 48 false,
48 false 49 false,
50 false,
51 ['offset' => 0, 'limit' => 2]
49 ) 52 )
50 ->willReturn([ 53 ->willReturn(SearchResult::getSearchResult([
51 (new Bookmark())->setId(1)->setUrl('http://url1.tld')->setTitle('Title 1'), 54 (new Bookmark())->setId(1)->setUrl('http://url1.tld')->setTitle('Title 1'),
52 (new Bookmark())->setId(2)->setUrl('http://url2.tld')->setTitle('Title 2'), 55 (new Bookmark())->setId(2)->setUrl('http://url2.tld')->setTitle('Title 2'),
53 (new Bookmark())->setId(3)->setUrl('http://url3.tld')->setTitle('Title 3'), 56 (new Bookmark())->setId(3)->setUrl('http://url3.tld')->setTitle('Title 3'),
54 ] 57 ], 0, 2)
55 ); 58 );
56 59
57 $this->container->sessionManager 60 $this->container->sessionManager
@@ -119,13 +122,15 @@ class BookmarkListControllerTest extends TestCase
119 ['searchtags' => '', 'searchterm' => ''], 122 ['searchtags' => '', 'searchterm' => ''],
120 null, 123 null,
121 false, 124 false,
122 false 125 false,
126 false,
127 ['offset' => 2, 'limit' => 2]
123 ) 128 )
124 ->willReturn([ 129 ->willReturn(SearchResult::getSearchResult([
125 (new Bookmark())->setId(1)->setUrl('http://url1.tld')->setTitle('Title 1'), 130 (new Bookmark())->setId(1)->setUrl('http://url1.tld')->setTitle('Title 1'),
126 (new Bookmark())->setId(2)->setUrl('http://url2.tld')->setTitle('Title 2'), 131 (new Bookmark())->setId(2)->setUrl('http://url2.tld')->setTitle('Title 2'),
127 (new Bookmark())->setId(3)->setUrl('http://url3.tld')->setTitle('Title 3'), 132 (new Bookmark())->setId(3)->setUrl('http://url3.tld')->setTitle('Title 3'),
128 ]) 133 ], 2, 2))
129 ; 134 ;
130 135
131 $this->container->sessionManager 136 $this->container->sessionManager
@@ -207,13 +212,15 @@ class BookmarkListControllerTest extends TestCase
207 ['searchtags' => 'abc@def', 'searchterm' => 'ghi jkl'], 212 ['searchtags' => 'abc@def', 'searchterm' => 'ghi jkl'],
208 'private', 213 'private',
209 false, 214 false,
210 true 215 true,
216 false,
217 ['offset' => 0, 'limit' => 2]
211 ) 218 )
212 ->willReturn([ 219 ->willReturn(SearchResult::getSearchResult([
213 (new Bookmark())->setId(1)->setUrl('http://url1.tld')->setTitle('Title 1'), 220 (new Bookmark())->setId(1)->setUrl('http://url1.tld')->setTitle('Title 1'),
214 (new Bookmark())->setId(2)->setUrl('http://url2.tld')->setTitle('Title 2'), 221 (new Bookmark())->setId(2)->setUrl('http://url2.tld')->setTitle('Title 2'),
215 (new Bookmark())->setId(3)->setUrl('http://url3.tld')->setTitle('Title 3'), 222 (new Bookmark())->setId(3)->setUrl('http://url3.tld')->setTitle('Title 3'),
216 ]) 223 ], 0, 2))
217 ; 224 ;
218 225
219 $result = $this->controller->index($request, $response); 226 $result = $this->controller->index($request, $response);
@@ -358,13 +365,13 @@ class BookmarkListControllerTest extends TestCase
358 $this->container->bookmarkService 365 $this->container->bookmarkService
359 ->expects(static::once()) 366 ->expects(static::once())
360 ->method('search') 367 ->method('search')
361 ->willReturn([ 368 ->willReturn(SearchResult::getSearchResult([
362 (new Bookmark())->setId(1)->setUrl('https://url1.tld')->setTitle('Title 1')->setThumbnail(false), 369 (new Bookmark())->setId(1)->setUrl('https://url1.tld')->setTitle('Title 1')->setThumbnail(false),
363 $b1 = (new Bookmark())->setId(2)->setUrl('https://url2.tld')->setTitle('Title 2'), 370 $b1 = (new Bookmark())->setId(2)->setUrl('https://url2.tld')->setTitle('Title 2'),
364 (new Bookmark())->setId(3)->setUrl('https://url3.tld')->setTitle('Title 3')->setThumbnail(false), 371 (new Bookmark())->setId(3)->setUrl('https://url3.tld')->setTitle('Title 3')->setThumbnail(false),
365 $b2 = (new Bookmark())->setId(2)->setUrl('https://url4.tld')->setTitle('Title 4'), 372 $b2 = (new Bookmark())->setId(2)->setUrl('https://url4.tld')->setTitle('Title 4'),
366 (new Bookmark())->setId(2)->setUrl('ftp://url5.tld', ['ftp'])->setTitle('Title 5'), 373 (new Bookmark())->setId(2)->setUrl('ftp://url5.tld', ['ftp'])->setTitle('Title 5'),
367 ]) 374 ]))
368 ; 375 ;
369 $this->container->bookmarkService 376 $this->container->bookmarkService
370 ->expects(static::exactly(2)) 377 ->expects(static::exactly(2))
diff --git a/tests/front/controller/visitor/DailyControllerTest.php b/tests/front/controller/visitor/DailyControllerTest.php
index 70fbce54..821ba321 100644
--- a/tests/front/controller/visitor/DailyControllerTest.php
+++ b/tests/front/controller/visitor/DailyControllerTest.php
@@ -5,6 +5,7 @@ declare(strict_types=1);
5namespace Shaarli\Front\Controller\Visitor; 5namespace Shaarli\Front\Controller\Visitor;
6 6
7use Shaarli\Bookmark\Bookmark; 7use Shaarli\Bookmark\Bookmark;
8use Shaarli\Bookmark\SearchResult;
8use Shaarli\Feed\CachedPage; 9use Shaarli\Feed\CachedPage;
9use Shaarli\TestCase; 10use Shaarli\TestCase;
10use Slim\Http\Request; 11use Slim\Http\Request;
@@ -347,13 +348,15 @@ class DailyControllerTest extends TestCase
347 $request = $this->createMock(Request::class); 348 $request = $this->createMock(Request::class);
348 $response = new Response(); 349 $response = new Response();
349 350
350 $this->container->bookmarkService->expects(static::once())->method('search')->willReturn([ 351 $this->container->bookmarkService->expects(static::once())->method('search')->willReturn(
351 (new Bookmark())->setId(1)->setCreated($dates[0])->setUrl('http://domain.tld/1'), 352 SearchResult::getSearchResult([
352 (new Bookmark())->setId(2)->setCreated($dates[1])->setUrl('http://domain.tld/2'), 353 (new Bookmark())->setId(1)->setCreated($dates[0])->setUrl('http://domain.tld/1'),
353 (new Bookmark())->setId(3)->setCreated($dates[1])->setUrl('http://domain.tld/3'), 354 (new Bookmark())->setId(2)->setCreated($dates[1])->setUrl('http://domain.tld/2'),
354 (new Bookmark())->setId(4)->setCreated($dates[2])->setUrl('http://domain.tld/4'), 355 (new Bookmark())->setId(3)->setCreated($dates[1])->setUrl('http://domain.tld/3'),
355 (new Bookmark())->setId(5)->setCreated($dates[3])->setUrl('http://domain.tld/5'), 356 (new Bookmark())->setId(4)->setCreated($dates[2])->setUrl('http://domain.tld/4'),
356 ]); 357 (new Bookmark())->setId(5)->setCreated($dates[3])->setUrl('http://domain.tld/5'),
358 ])
359 );
357 360
358 $this->container->pageCacheManager 361 $this->container->pageCacheManager
359 ->expects(static::once()) 362 ->expects(static::once())
@@ -454,7 +457,9 @@ class DailyControllerTest extends TestCase
454 $request = $this->createMock(Request::class); 457 $request = $this->createMock(Request::class);
455 $response = new Response(); 458 $response = new Response();
456 459
457 $this->container->bookmarkService->expects(static::once())->method('search')->willReturn([]); 460 $this->container->bookmarkService
461 ->expects(static::once())->method('search')
462 ->willReturn(SearchResult::getSearchResult([]));
458 463
459 // Save RainTPL assigned variables 464 // Save RainTPL assigned variables
460 $assignedVariables = []; 465 $assignedVariables = [];
@@ -613,11 +618,13 @@ class DailyControllerTest extends TestCase
613 }); 618 });
614 $response = new Response(); 619 $response = new Response();
615 620
616 $this->container->bookmarkService->expects(static::once())->method('search')->willReturn([ 621 $this->container->bookmarkService->expects(static::once())->method('search')->willReturn(
617 (new Bookmark())->setId(1)->setCreated($dates[0])->setUrl('http://domain.tld/1'), 622 SearchResult::getSearchResult([
618 (new Bookmark())->setId(2)->setCreated($dates[1])->setUrl('http://domain.tld/2'), 623 (new Bookmark())->setId(1)->setCreated($dates[0])->setUrl('http://domain.tld/1'),
619 (new Bookmark())->setId(3)->setCreated($dates[1])->setUrl('http://domain.tld/3'), 624 (new Bookmark())->setId(2)->setCreated($dates[1])->setUrl('http://domain.tld/2'),
620 ]); 625 (new Bookmark())->setId(3)->setCreated($dates[1])->setUrl('http://domain.tld/3'),
626 ])
627 );
621 628
622 // Save RainTPL assigned variables 629 // Save RainTPL assigned variables
623 $assignedVariables = []; 630 $assignedVariables = [];
@@ -674,11 +681,13 @@ class DailyControllerTest extends TestCase
674 }); 681 });
675 $response = new Response(); 682 $response = new Response();
676 683
677 $this->container->bookmarkService->expects(static::once())->method('search')->willReturn([ 684 $this->container->bookmarkService->expects(static::once())->method('search')->willReturn(
678 (new Bookmark())->setId(1)->setCreated($dates[0])->setUrl('http://domain.tld/1'), 685 SearchResult::getSearchResult([
679 (new Bookmark())->setId(2)->setCreated($dates[1])->setUrl('http://domain.tld/2'), 686 (new Bookmark())->setId(1)->setCreated($dates[0])->setUrl('http://domain.tld/1'),
680 (new Bookmark())->setId(3)->setCreated($dates[1])->setUrl('http://domain.tld/3'), 687 (new Bookmark())->setId(2)->setCreated($dates[1])->setUrl('http://domain.tld/2'),
681 ]); 688 (new Bookmark())->setId(3)->setCreated($dates[1])->setUrl('http://domain.tld/3'),
689 ])
690 );
682 691
683 // Save RainTPL assigned variables 692 // Save RainTPL assigned variables
684 $assignedVariables = []; 693 $assignedVariables = [];
diff --git a/tests/front/controller/visitor/PictureWallControllerTest.php b/tests/front/controller/visitor/PictureWallControllerTest.php
index b868231d..429e99a2 100644
--- a/tests/front/controller/visitor/PictureWallControllerTest.php
+++ b/tests/front/controller/visitor/PictureWallControllerTest.php
@@ -5,6 +5,7 @@ declare(strict_types=1);
5namespace Shaarli\Front\Controller\Visitor; 5namespace Shaarli\Front\Controller\Visitor;
6 6
7use Shaarli\Bookmark\Bookmark; 7use Shaarli\Bookmark\Bookmark;
8use Shaarli\Bookmark\SearchResult;
8use Shaarli\Config\ConfigManager; 9use Shaarli\Config\ConfigManager;
9use Shaarli\Front\Exception\ThumbnailsDisabledException; 10use Shaarli\Front\Exception\ThumbnailsDisabledException;
10use Shaarli\TestCase; 11use Shaarli\TestCase;
@@ -50,17 +51,17 @@ class PictureWallControllerTest extends TestCase
50 $this->container->bookmarkService 51 $this->container->bookmarkService
51 ->expects(static::once()) 52 ->expects(static::once())
52 ->method('search') 53 ->method('search')
53 ->willReturnCallback(function (array $parameters, ?string $visibility): array { 54 ->willReturnCallback(function (array $parameters, ?string $visibility): SearchResult {
54 // Visibility is set through the container, not the call 55 // Visibility is set through the container, not the call
55 static::assertNull($visibility); 56 static::assertNull($visibility);
56 57
57 // No query parameters 58 // No query parameters
58 if (count($parameters) === 0) { 59 if (count($parameters) === 0) {
59 return [ 60 return SearchResult::getSearchResult([
60 (new Bookmark())->setId(1)->setUrl('http://url.tld')->setThumbnail('thumb1'), 61 (new Bookmark())->setId(1)->setUrl('http://url.tld')->setThumbnail('thumb1'),
61 (new Bookmark())->setId(2)->setUrl('http://url2.tld'), 62 (new Bookmark())->setId(2)->setUrl('http://url2.tld'),
62 (new Bookmark())->setId(3)->setUrl('http://url3.tld')->setThumbnail('thumb2'), 63 (new Bookmark())->setId(3)->setUrl('http://url3.tld')->setThumbnail('thumb2'),
63 ]; 64 ]);
64 } 65 }
65 }) 66 })
66 ; 67 ;