]> git.immae.eu Git - github/shaarli/Shaarli.git/blobdiff - application/bookmark/SearchResult.php
Handle pagination through BookmarkService
[github/shaarli/Shaarli.git] / application / bookmark / SearchResult.php
diff --git a/application/bookmark/SearchResult.php b/application/bookmark/SearchResult.php
new file mode 100644 (file)
index 0000000..c0bce31
--- /dev/null
@@ -0,0 +1,136 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Shaarli\Bookmark;
+
+/**
+ * Read-only class used to represent search result, including pagination.
+ */
+class SearchResult
+{
+    /** @var Bookmark[] List of result bookmarks with pagination applied */
+    protected $bookmarks;
+
+    /** @var int number of Bookmarks found, with pagination applied */
+    protected $resultCount;
+
+    /** @var int total number of result found */
+    protected $totalCount;
+
+    /** @var int pagination: limit number of result bookmarks */
+    protected $limit;
+
+    /** @var int pagination: offset to apply to complete result list */
+    protected $offset;
+
+    public function __construct(array $bookmarks, int $totalCount, int $offset, ?int $limit)
+    {
+        $this->bookmarks = $bookmarks;
+        $this->resultCount = count($bookmarks);
+        $this->totalCount = $totalCount;
+        $this->limit = $limit;
+        $this->offset = $offset;
+    }
+
+    /**
+     * Build a SearchResult from provided full result set and pagination settings.
+     *
+     * @param Bookmark[] $bookmarks        Full set of result which will be filtered
+     * @param int        $offset           Start recording results from $offset
+     * @param int|null   $limit            End recording results after $limit bookmarks is reached
+     * @param bool       $allowOutOfBounds Set to false to display the last page if the offset is out of bound,
+     *                                     return empty result set otherwise (default: false)
+     *
+     * @return SearchResult
+     */
+    public static function getSearchResult(
+        $bookmarks,
+        int $offset = 0,
+        ?int $limit = null,
+        bool $allowOutOfBounds = false
+    ): self {
+        $totalCount = count($bookmarks);
+        if (!$allowOutOfBounds && $offset > $totalCount) {
+            $offset = $limit === null ? 0 : $limit * -1;
+        }
+
+        if ($bookmarks instanceof BookmarkArray) {
+            $buffer = [];
+            foreach ($bookmarks as $key => $value) {
+                $buffer[$key] = $value;
+            }
+            $bookmarks = $buffer;
+        }
+
+        return new static(
+            array_slice($bookmarks, $offset, $limit, true),
+            $totalCount,
+            $offset,
+            $limit
+        );
+    }
+
+    /** @return Bookmark[] List of result bookmarks with pagination applied */
+    public function getBookmarks(): array
+    {
+        return $this->bookmarks;
+    }
+
+    /** @return int number of Bookmarks found, with pagination applied */
+    public function getResultCount(): int
+    {
+        return $this->resultCount;
+    }
+
+    /** @return int total number of result found */
+    public function getTotalCount(): int
+    {
+        return $this->totalCount;
+    }
+
+    /** @return int pagination: limit number of result bookmarks */
+    public function getLimit(): ?int
+    {
+        return $this->limit;
+    }
+
+    /** @return int pagination: offset to apply to complete result list */
+    public function getOffset(): int
+    {
+        return $this->offset;
+    }
+
+    /** @return int Current page of result set in complete results */
+    public function getPage(): int
+    {
+        if (empty($this->limit)) {
+            return $this->offset === 0 ? 1 : 2;
+        }
+        $base = $this->offset >= 0 ? $this->offset : $this->totalCount + $this->offset;
+
+        return (int) ceil($base / $this->limit) + 1;
+    }
+
+    /** @return int Get the # of the last page */
+    public function getLastPage(): int
+    {
+        if (empty($this->limit)) {
+            return $this->offset === 0 ? 1 : 2;
+        }
+
+        return (int) ceil($this->totalCount / $this->limit);
+    }
+
+    /** @return bool Either the current page is the last one or not */
+    public function isLastPage(): bool
+    {
+        return $this->getPage() === $this->getLastPage();
+    }
+
+    /** @return bool Either the current page is the first one or not */
+    public function isFirstPage(): bool
+    {
+        return $this->offset === 0;
+    }
+}